graphene-file-upload
graphene-file-upload copied to clipboard
No UI example found
We are trying to use this in our project not able to create a ui not even properly test.we need an documentation/ examples including ui
What do you mean by UI example?
There is no client side code in the example only backend code is there. A React.JS implementation is missing in the example.
This is a backend implementation for GraphQL multipart specification. There separate frontend repositories for different frameworks and libraries. Here is the repo for the specification: https://github.com/jaydenseric/graphql-multipart-request-spec/blob/master/readme.md. If you check the end of README, you will see different repos for frameworks / libraries for both client and server.
I think it doesn’t make sense to show examples for frontend here because it is based on a specification written by a 3rd party. Plus, If React example is added, Angular and Vue examples should also be added. The specification’s repo has all the necessary information for different tools.
for those who are still struggling with this (as I did) here is a code that may help Please be aware of the endpoint URL, which has to be adjusted to your needs.
import { print } from 'graphql/language/printer';
const createOptions = (opts) => {
const formData = new FormData();
opts.variables.files.forEach((file, i) => {
formData.append('map', `{"${i}": ["variables.files.${i}"] }`);
formData.append(`${i}`, file, file.name);
});
const files_null = opts.variables.files.map(() => null) // one null for each file, e.g. "null,null,null"
const variables = {...opts.variables}
variables.files = files_null
//see https://stackoverflow.com/questions/57490569/import-graphql-query-gql-file-into-plain-javascript-and-run-an-axios-call
const value = {
query: print(opts.query),
variables: variables
}
formData.append('operations', JSON.stringify(value).replace(/\\n/g, ''))
return {
method: 'POST',
credentials: 'include',
body: formData,
}
}
const uploadFile = (opts) => {
console.assert(opts.variables.files.length > 0, 'files is empty');
return fetch(
`${process.env.NEXT_PUBLIC_BACKEND}upload/`,
createOptions(opts)
);
};
// const [uploadFiles, { status }] = useUploadFiles()
export default uploadFile;
Mutation
export const UPLOAD_FILES = gql`
mutation uploadFiles($files: [Upload]!) {
uploadFiles(files: $files) {
ok
urls {
url
name
}
}
}
`
Call: just use an input type="file" and call
uploadFIle({query: UPLOAD_FILES, variables: { files: [e.target.files[0]] }}
@luiskarlos I am doing the same thing, but getting an empty dict on the server (Django/graphene) side. Also in that last line you posted, it should be 'mutation: UPLOAD_FILES' rather than 'query: UPLOAD_FILES', right? Here is my (failing) code. Perhaps you (or someone else) can spot something obvious:
const UPLOAD_NEW_FILE = gql `
mutation UploadNewFile($fileToUpload: Upload!) {
uploadNewFile(file: $fileToUpload) {
success
}
}`;
uploadFile(agFile: File): Observable<FetchResult<any>> {
return this.apollo.mutate({
mutation: UPLOAD_NEW_FILE,
variables: {
fileToUpload: agFile
}
});
And I am calling this method like this:
onFileUpload(event) {
const myFile = event.target.files[0]
this.configSvc.uploadFile(myFile).subscribe(({ data }) => {
console.log("Upload of package was " + data.success)
})
}
onFileUpload is invoked from an 'input type="file" HTML element. I have printed (console.log) the myFile variable in onFileUpload handler function and the 'agFile' variable in the uploadFile service function right before the mutation call, and they indeed are file objects. But for whatever reason, when apollo picks it up it makes it into an empty dict.
Any help is much appreciated.
Also adding that the above mutation is working from the Altair graphql client.
@boomdizz This is the code I am using right now, my backend is with python so I am not sure how it will work with js:
this is a utility uploadFile.js
import { print } from 'graphql/language/printer';
const createOptions = (opts) => {
const formData = new FormData();
opts.variables.files.forEach((file, i) => {
formData.append('map', `{"${i}": ["variables.files.${i}"] }`);
formData.append(`${i}`, file, file.name);
});
const files_null = opts.variables.files.map(() => null); // one null for each file, e.g. "null,null,null"
const variables = { ...opts.variables };
variables.files = files_null;
//see https://stackoverflow.com/questions/57490569/import-graphql-query-gql-file-into-plain-javascript-and-run-an-axios-call
const value = {
query: print(opts.query),
variables: variables,
};
formData.append('operations', JSON.stringify(value).replace(/\\n/g, ''));
return {
method: 'POST',
credentials: 'include',
body: formData,
};
};
const uploadFile = (opts) => {
console.assert(opts.variables.files.length > 0, 'files is empty');
return fetch(
`${process.env.NEXT_PUBLIC_BACKEND}upload/`,
createOptions(opts)
);
};
export default uploadFile;
This a hook
import { useEffect, useState } from 'react';
import uploadFile from '../utils/uploadFile';
const useUpload = (query) => {
const [options, upload] = useState({ variables: {} });
const [status, setStatus] = useState({
uploading: false,
success: false,
error: false,
data: null,
message: null,
});
const updateStatus = (uploading, success, error, data, message) =>
setStatus({ uploading, success, error, data, message });
useEffect(() => {
if (options.variables?.files?.length) {
updateStatus(true, false, false, null, 'Uploading...');
uploadFile({ query, ...options })
.then((result) => {
return result.json();
})
.then((result) => {
if (result.errors) {
throw new Error(result.errors[0].message);
}
updateStatus(
false,
true,
false,
result.data,
'Files Uploaded Successfully'
);
})
.catch((error) => {
updateStatus(false, false, true, error.message);
console.log('error', error);
});
}
}, [options]);
return [upload, { ...status }];
};
// const [uploadFiles, { status }] = useUploadFiles()
export default useUpload;
This is the query:
export const UPLOAD_FILES = gql`
mutation uploadFiles($files: [Upload]!) {
uploadFiles(files: $files) {
ok
}
}
`;
This is my mutation:
class UploadFilesMutation(graphene.Mutation):
class Arguments:
files = graphene.List(Upload)
file = graphene.Field(FileType)
def mutate(self, info, files, **kwargs):
rf = StorageSystem.save_file(info.context.user, files[0], public=False)
return UploadFilesMutation(document=document)
I was able to finally get it to work in the Angular/Apollo environment. I have it documented as the answer to my own question on Stackoverflow