GraphQL Upload for TypeScript

raw JSON →
2.1.4 verified Thu Apr 23 auth: no javascript

`graphql-upload-ts` is a TypeScript-first library designed to facilitate file uploads within GraphQL applications by providing specialized middleware and an `Upload` scalar type. The current stable version is `2.1.4`, reflecting active development with frequent beta releases. This package distinguishes itself through comprehensive TypeScript support, ensuring type-safety and robust integration across various Node.js frameworks, including Express, Koa, Apollo Server, and GraphQL Yoga. It's built for production environments, featuring efficient file streaming, high test coverage, and compatibility with the Bun runtime. A strong emphasis on security is evident through built-in file validation capabilities, and it supports both CommonJS and ESM module systems for broad project compatibility. Its detailed documentation and example implementations further enhance its usability for developers integrating file upload functionality into their GraphQL APIs.

error Error: Unknown type "Upload". Did you mean "Boolean" or "String"?
cause The `GraphQLUpload` scalar type was not included or correctly referenced in your GraphQL schema definition.
fix
Ensure GraphQLUpload is imported from graphql-upload-ts and added to your schema's type definitions, e.g., in a types array for GraphQLSchema or explicitly referenced in your schema language definition.
error Error: Request must be a multipart request.
cause The client request sent was not `multipart/form-data`, or the `graphqlUploadExpress` middleware was not correctly applied or ordered.
fix
Verify that your client is sending a Content-Type: multipart/form-data header. Double-check that graphqlUploadExpress is correctly used and placed *before* your primary GraphQL HTTP handler middleware.
error TypeError: Cannot read properties of undefined (reading 'createReadStream')
cause The `file` argument in your resolver is `undefined` or not the expected `FileUpload` object, typically indicating a problem with the multipart request parsing or schema definition.
fix
Confirm that the file argument in your GraphQL mutation is correctly typed as GraphQLUpload in the schema. Ensure the client's multipart request correctly maps the file input to the file argument in the GraphQL query variables.
gotcha The `graphqlUploadExpress` middleware must be applied *before* your main GraphQL HTTP middleware (e.g., `express-graphql`, Apollo Server's middleware) to correctly parse multipart requests. Incorrect order will prevent file uploads from being processed.
fix Ensure `app.use(graphqlUploadExpress({ ... }));` is declared and invoked prior to `app.use('/graphql', graphqlHTTP({ ... }));` or your Apollo Server integration.
gotcha The library requires Node.js version 16 or newer. Running on older Node.js environments may lead to unexpected runtime errors or instability due to reliance on modern JavaScript features and API availability.
fix Upgrade your Node.js runtime to version 16.0.0 or higher to meet the minimum engine requirements.
gotcha By default, `graphql-upload-ts` has limits for file size (`maxFileSize`), number of files (`maxFiles`), and total fields (`maxFieldSize`). Exceeding these limits, especially for large files or numerous uploads, can lead to server crashes or resource exhaustion (e.g., out-of-memory errors).
fix Explicitly configure these limits in the `graphqlUploadExpress` options. For example: `graphqlUploadExpress({ maxFileSize: 20000000, maxFiles: 5 })` for 20MB files and 5 files maximum. Implement custom stream processing for extremely large files to avoid buffering entirely.
npm install graphql-upload-ts
yarn add graphql-upload-ts
pnpm add graphql-upload-ts

This quickstart demonstrates setting up a basic GraphQL server with Express and `graphql-upload-ts` to handle file upload mutations. It configures the necessary middleware and defines a simple schema with an `uploadFile` mutation.

import express from 'express';
import { graphqlHTTP } from 'express-graphql';
import { graphqlUploadExpress, GraphQLUpload } from 'graphql-upload-ts';
import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      hello: {
        type: GraphQLString,
        resolve: () => 'Hello World',
      },
    },
  }),
  mutation: new GraphQLObjectType({
    name: 'Mutation',
    fields: {
      uploadFile: {
        type: GraphQLString,
        args: {
          file: { type: GraphQLUpload },
        },
        async resolve(_, { file }) {
          const { filename, createReadStream } = await file;
          const stream = createReadStream();
          // Example: Save file to disk or cloud storage
          // stream.pipe(fs.createWriteStream(`./uploads/${filename}`));
          console.log(`Processing file: ${filename}`);
          await new Promise(resolve => stream.on('end', resolve)); // Wait for stream to finish
          return `File ${filename} uploaded successfully`;
        },
      },
    },
  }),
});

const app = express();

// Important: graphqlUploadExpress middleware must come BEFORE graphqlHTTP
app.use(
  '/graphql',
  graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }), // 10 MB limit per file, 10 files max
  graphqlHTTP({
    schema,
    graphiql: true, // Enable GraphiQL for easy testing
  }),
);

const PORT = process.env.PORT ?? 4000;
app.listen(PORT, () => {
  console.log(`GraphQL server running on http://localhost:${PORT}/graphql`);
});