GraphQL Upload for TypeScript
raw JSON →`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.
Common errors
error Error: Unknown type "Upload". Did you mean "Boolean" or "String"? ↓
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. ↓
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') ↓
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. Warnings
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. ↓
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. ↓
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). ↓
Install
npm install graphql-upload-ts yarn add graphql-upload-ts pnpm add graphql-upload-ts Imports
- graphqlUploadExpress wrong
const { graphqlUploadExpress } = require('graphql-upload-ts');correctimport { graphqlUploadExpress } from 'graphql-upload-ts'; - GraphQLUpload wrong
const { GraphQLUpload } = require('graphql-upload-ts');correctimport { GraphQLUpload } from 'graphql-upload-ts'; - FileUpload
import { FileUpload } from 'graphql-upload-ts';
Quickstart
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`);
});