0
0
GraphqlHow-ToBeginner · 3 min read

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 Upload scalar and multipart requests will cause errors.
  • Forgetting to configure middleware like graphql-upload in older Apollo Server versions.
  • Trying to send files as base64 strings instead of using multipart form data.
  • Not awaiting the file promise 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

StepDescription
Define Upload scalarAdd scalar Upload in your schema.
Create mutationDefine mutation with file: Upload! argument.
Use compatible serverUse Apollo Server or similar with upload support.
Handle file in resolverAwait the file promise and process the stream.
Send multipart requestClient 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.