How to Use Mutation with File Upload in GraphQL
To use a
mutation with file upload in GraphQL, you need to implement the multipart request specification which allows sending files as Upload scalar types. This involves defining a mutation that accepts an Upload type and using a GraphQL server like Apollo Server that supports file uploads.Syntax
A GraphQL mutation for file upload uses the Upload scalar type to accept files. The client sends a multipart/form-data request where the file is mapped to the Upload variable.
Key parts:
Upload: A special scalar type representing the file.mutation uploadFile($file: Upload!): Mutation definition with a file variable.file: The variable holding the uploaded file.
graphql
mutation uploadFile($file: Upload!) {
uploadFile(file: $file) {
filename
mimetype
encoding
}
}Example
This example shows a simple Apollo Server setup with a mutation to upload a file and return its metadata.
javascript
const { ApolloServer, gql } = require('apollo-server'); const { GraphQLUpload } = require('graphql-upload'); const typeDefs = gql` scalar Upload type File { filename: String! mimetype: String! encoding: String! } type Mutation { uploadFile(file: Upload!): File! } `; const resolvers = { Upload: GraphQLUpload, Mutation: { uploadFile: async (_, { file }) => { const { filename, mimetype, encoding, createReadStream } = await file; // Here you could save the file stream to disk or cloud storage // For demo, just return file info return { filename, mimetype, encoding }; }, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
Output
Server ready at http://localhost:4000/
Common Pitfalls
- Not using a GraphQL server that supports the
Uploadscalar and multipart requests will cause errors. - Forgetting to configure middleware like
graphql-uploadin older Apollo Server versions. - Trying to send files as base64 strings instead of using multipart form data.
- Not awaiting the
filepromise in the resolver, which leads to unresolved streams.
javascript
/* Wrong: Not awaiting file promise */ uploadFile: (_, { file }) => { const { filename } = file; // file is a promise, this is wrong return { filename }; } /* Right: Await the file promise */ uploadFile: async (_, { file }) => { const { filename } = await file; return { filename }; }
Quick Reference
| Step | Description |
|---|---|
| Define Upload scalar | Add scalar Upload in your schema. |
| Create mutation | Define mutation with file: Upload! argument. |
| Use compatible server | Use Apollo Server or similar with upload support. |
| Handle file in resolver | Await the file promise and process the stream. |
| Send multipart request | Client sends file using multipart/form-data. |
Key Takeaways
Use the Upload scalar type in your mutation to accept files.
Ensure your GraphQL server supports multipart requests for file uploads.
Always await the file promise in your resolver to access file details.
Clients must send files using multipart/form-data, not base64 strings.
Configure middleware if your server version requires it for uploads.