I am trying to upload image from (react + Ant Design) client-side to (Node.js) server via GraphQL but I am getting this error in the form server
Could not create Operator: TypeError: Cannot read properties of undefined (reading 'filename')
I have tested the mutation through Postman and it works correctly
This is the frontend code:
const [fileList, setFileList] = useState<File[]>([]);
<Form.Item name={"files"} label="Image" valuePropName='fileList'
getValueFromEvent={(event)=>{
return event?.fileList
}}>
<Upload accept="image/png, image/jpeg" maxCount={1}
fileList={fileList as any}
beforeUpload={(_, fileList) => {
setFileList(fileList);
return false;
}}
customRequest={(info)=>{
setFileList([info?.file as File])
}}
showUploadList={false}
listType="picture-card">
<div>
<PlusOutlined />
<div style={{ marginTop: 8 }}>Upload image</div>
{fileList[0]?.name}
</div>
</Upload>
</Form.Item>
The mutation takes 2 arguments (input data and file):
type Mutation {
createOperator(request: OperatorInput, file: Upload): Operator
}
I'm passing the params to the mutation like this:
const [mutation, { loading }] = useMutation<Response, Request>(CREATE_OPERATOR);
const result = await mutation({ variables: { request, file } });
What I realized that via postman request the file will reach the server and it includes:
Upload {
resolve: [Function (anonymous)],
reject: [Function (anonymous)],
promise: Promise {
{
fieldName: '0',
filename: 'IMG_20230411_181040.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: [Function: createReadStream]
}
},
file: {
fieldName: '0',
filename: 'IMG_20230411_181040.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: [Function: createReadStream]
}
}
And this is correct, then I am using it to save the image in the Cloud. But from the client-side am not getting this promise and the above attributes.
It just an object contains the following:
{
uid: 'rc-upload-1690197951111-71',
lastModified: 1688137614360,
lastModifiedDate: '2023-06-30T15:06:54.360Z',
name: 'IMG_20230411_181040.jpg',
size: 13313470,
type: 'image/jpeg',
percent: 0,
originFileObj: { uid: 'rc-upload-1690197951111-71' }
}
I assume that my frontend code is not sending the file correctly.
The solution was to enable the multipart request on the client-side in the index.js file by adding link: createUploadLink()
instead of link: new HttpLink
I am using graphql-upload on server-side
See below:
import { createUploadLink } from 'apollo-upload-client';
const option = {
uri: "http://localhost:4000/graphql",
credentials: "include"
}
const client = new ApolloClient({
cache: new InMemoryCache(),
link: createUploadLink(option),
/*link: new HttpLink({
uri: "http://localhost:4000/graphql",
credentials: "include"
}),*/
});
For more details, see the installation section of apollo-upload-client