0
0
GraphqlHow-ToBeginner · 4 min read

How to Use GraphQL Upload: Syntax, Example, and Tips

To use graphql-upload, add the GraphQLUpload scalar to your schema and use it as an argument type for file uploads. Then, handle the uploaded file in your resolver by processing the FileUpload object which contains file stream and metadata.
📐

Syntax

The graphql-upload package provides a special scalar type GraphQLUpload to handle file uploads in GraphQL. You define an argument of this type in your mutation to accept files.

Example parts:

  • scalar Upload: Declares the upload scalar in your schema.
  • upload: Upload!: Mutation argument to receive the file.
  • FileUpload object: The resolver receives this object with filename, mimetype, and createReadStream() to access the file data.
graphql
scalar Upload

type Mutation {
  singleUpload(file: Upload!): File!
}

type File {
  filename: String!
  mimetype: String!
  encoding: String!
}
💻

Example

This example shows a simple GraphQL server using graphql-upload to accept a single file upload. The resolver saves the file to disk and returns file info.

javascript
import { ApolloServer, gql } from 'apollo-server';
import { GraphQLUpload, graphqlUploadExpress } from 'graphql-upload';
import fs from 'fs';
import path from 'path';

const typeDefs = gql`
  scalar Upload

  type File {
    filename: String!
    mimetype: String!
    encoding: String!
  }

  type Mutation {
    singleUpload(file: Upload!): File!
  }
`;

const resolvers = {
  Upload: GraphQLUpload,
  Mutation: {
    async singleUpload(parent, { file }) {
      const { createReadStream, filename, mimetype, encoding } = await file;
      const stream = createReadStream();
      const outPath = path.join(__dirname, 'uploads', filename);
      const out = fs.createWriteStream(outPath);
      stream.pipe(out);
      await new Promise((resolve, reject) => {
        out.on('finish', resolve);
        out.on('error', reject);
      });
      return { filename, mimetype, encoding };
    }
  }
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  uploads: false
});

import express from 'express';
const app = express();
app.use(graphqlUploadExpress());
server.start().then(() => {
  server.applyMiddleware({ app });
  app.listen({ port: 4000 }, () => {
    console.log('Server ready at http://localhost:4000' + server.graphqlPath);
  });
});
Output
Server ready at http://localhost:4000/graphql
⚠️

Common Pitfalls

  • Not adding graphqlUploadExpress() middleware in your server setup causes uploads to fail.
  • Forgetting to declare scalar Upload in your schema leads to schema errors.
  • Not handling the file stream properly can cause memory leaks or incomplete uploads.
  • Setting uploads: false in ApolloServer without middleware disables upload support.
graphql
/* Wrong: Missing middleware and scalar declaration */
const typeDefsWrong = gql`
  type Mutation {
    singleUpload(file: Upload!): File!
  }
`;

/* Right: Add scalar and middleware */
const typeDefsRight = gql`
  scalar Upload
  type Mutation {
    singleUpload(file: Upload!): File!
  }
`;

app.use(graphqlUploadExpress());
📊

Quick Reference

StepDescription
1. Add scalar UploadDeclare scalar Upload in your GraphQL schema.
2. Use Upload in mutationAdd an argument of type Upload! to your mutation.
3. Add middlewareUse graphqlUploadExpress() middleware in your server.
4. Handle file in resolverUse createReadStream() to process the uploaded file.
5. Return file infoReturn file metadata like filename and mimetype from resolver.

Key Takeaways

Always declare scalar Upload in your schema to enable file uploads.
Use graphqlUploadExpress() middleware to parse multipart requests.
Handle the file stream in your resolver to save or process the uploaded file.
Return useful file metadata to confirm successful upload.
Avoid disabling uploads by setting uploads: false without middleware.