File uploads
Enabling file uploads in Apollo Server
You can add file upload support to Apollo Server via the third-party graphql-upload
library. This package provides support for the multipart/form-data
content-type.
New in Apollo Server 3: Apollo Server 3 does not contain a built-in integration with graphql-upload
like in Apollo Server 2. Instead, the instructions below show how to integrate it yourself. You cannot do this with the "batteries-included" apollo-server
library; you must use a web framework integration such as apollo-server-express
instead. To implement similar functionality with another Node.js HTTP framework (e.g., Koa), see the graphql-upload
documentation for more information. Some integrations might need to use graphql-upload
's processRequest
directly.
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const {
GraphQLUpload,
graphqlUploadExpress, // A Koa implementation is also exported.
} = require('graphql-upload');
const { finished } = require('stream/promises');
const typeDefs = gql`
# The implementation for this scalar is provided by the
# 'GraphQLUpload' export from the 'graphql-upload' package
# in the resolver map below.
scalar Upload
type File {
filename: String!
mimetype: String!
encoding: String!
}
type Query {
# This is only here to satisfy the requirement that at least one
# field be present within the 'Query' type. This example does not
# demonstrate how to fetch uploads back.
otherFields: Boolean!
}
type Mutation {
# Multiple uploads are supported. See graphql-upload docs for details.
singleUpload(file: Upload!): File!
}
`;
const resolvers = {
// This maps the `Upload` scalar to the implementation provided
// by the `graphql-upload` package.
Upload: GraphQLUpload,
Mutation: {
singleUpload: async (parent, { file }) => {
const { createReadStream, filename, mimetype, encoding } = await file;
// Invoking the `createReadStream` will return a Readable Stream.
// See https://nodejs.org/api/stream.html#stream_readable_streams
const stream = createReadStream();
// This is purely for demonstration purposes and will overwrite the
// local-file-output.txt in the current working directory on EACH upload.
const out = require('fs').createWriteStream('local-file-output.txt');
stream.pipe(out);
await finished(out);
return { filename, mimetype, encoding };
},
},
};
async function startServer() {
const server = new ApolloServer({
typeDefs,
resolvers,
});
await server.start();
const app = express();
// This middleware should be added before calling `applyMiddleware`.
app.use(graphqlUploadExpress());
server.applyMiddleware({ app });
await new Promise(r => app.listen({ port: 4000 }, r));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
startServer();