All implementations and extensions are based on graphql-multipart-request-spec
Client is using apollo-upload-client which implemented graphql-multipart-request-spec
Replace HttpLink
with createUploadLink
Those two do the same thing, feel free to replace it!
import {
ApolloClient,
InMemoryCache
} from '@apollo/client';
import {
createUploadLink
} from 'apollo-upload-client';
const client = new ApolloClient(config);
Upload scalar
Due to different dependencies, this may cause some error, see Troubleshooting below
type Mutation {
singleUpload(file: Upload!): File!
}
type File {
filename: String!
mimetype: String!
encoding: String!
}
Provide an input or use other frontend components to select a file:
<input type="file" onchange={fileUpload}>
Then validate the selected file:
const uploadOnChange = async (files: File[]) => {
if (files.length === 0) return
if (files.filter((file) => file.size > 10 * 1024 * 1024).length > 0) {
/* throw error: file size exceed */
return
}
if (
files.filter(
(file) => [ `image/png` , `image/jpeg` ].findIndex(
(type) => file.type === type
) === -1
).length > 0
) {
/* throw error: unacceptable file type */
return
}
/* trigger mutation here */
}
If you are using Javascript, skip the import of
graphql-upload
If you are using Typescript, you can use graphql-upload for type check, which implemented graphql-multipart-request-spec
import { FileUpload } from "graphql-upload";
const uploadFile = async (filePromise: {
file: FileUpload;
}): Promise<boolean> => {
try {
const { file }: { file: FileUpload } = await filePromise;
const fileReadStream = file.createReadStream(); // get the file readstream
/* ----------------------------- `*/
/* Option 1: You can save the file on current server */
/* const writeStream = fs.createWriteStream('fakepath/output.png') */
/* Convert stream to file */
/* readStream.pipe(writeStream) */
/* ----------------------------- */
/* Option 2: You can port the file to assets server if you need */
const formData = new FormData();
formData.append("attachmentData", fileReadStream, file.filename);
await http.post( `assetsServer/fileUpload` , formData, {
headers: {
...formData.getHeaders(),
},
timeout: 30000,
});
return true;
} catch (error) {
return false;
}
};
const resolvers = {
Query: {
files: () => {
// Return the record of files uploaded from your DB or API or filesystem.
}
},
Mutation: {
uploadFile
},
};
Possibly you included one lib which ALREADY implemented Upload Type, so you just need to delete scalar Upload
You forget to add the scalar Upload
scalar Upload
always causes error :(
Error: There can be only one type named "Upload"
Error: Unknown type "Upload". Did you mean "Float"?
Oh you got some tricky dependencies.Try use other names like:
scalar FileUpload
That may help your issue, GraphQL may regard it as custom scalar.
RangeError: Maximum call stack size exceeded
at _openReadFs (internal/fs/streams.js:1:1)
This is due to outdated dependency of fs-capacitor
.
To prevent future compatibility issue, set resolutions
in package.json
:
"resolutions": {
"graphql-upload": "11.0.0"
},
Be aware that resolutions property is currently only handled by yarn package manager, not by npm
with npm, you have to preinstall an aditionnal module to force resolutions :
"scripts": {
"preinstall": "npx npm-force-resolutions",
}