File Uploads
GraphQL Yoga supports GraphQL Multipart Request Specification which allows you to upload files via HTTP and consume the binary data inside GraphQL Resolvers.
In GraphQL Yoga, you consume uploaded files or blobs as WHATWG standard File
or Blob
objects you might be familiar from the browser's API.
Check out MDN documentation to learn more about File
objects.
You can use any kind of client to support GraphQL Upload specification. Check out here to find GraphQL Client solutions.
Example
You only need to add a scalar type definition for file uploads in your schema. The name of the scalar doesn't matter.
Let's use File
in this example:
import fs from 'node:fs/promises'
import path from 'node:path'
import { createServer } from '@graphql-yoga/node'
// Provide your schema
const server = createServer({
schema: {
typeDefs: /* GraphQL */ `
scalar File
type Query {
greetings: String!
}
type Mutation {
readTextFile(file: File!): String!
saveFile(file: File!): Boolean
}
`,
resolvers: {
Query: {
greetings: () => 'Hello World!'
},
Mutation: {
/**
* TypeScript type `File` is globally available.
* You don't need to install/import anything else
* for both `File` GraphQL Scalar and this type
*/
async readTextFile(_, { file }: { file: File }) {
const textContent = await file.text()
return textContent
},
async saveFile(_, { file }: { file: File }) {
try {
const fileStream = file.stream()
await fs.writeFile(path.join(__dirname, file.name), fileStream)
return true
} catch {
return false
}
}
}
}
}
})
// Start the server and explore http://localhost:4000/graphql
server.start()
Test Your GraphQL Server with cURL
curl localhost:4000/graphql \
-F operations='{ "query": "mutation ($file: File!) { readTextFile(file: $file) }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@mytext.txt
With GraphQL Nexus
You need to create a scalar type for file upload in your schema:
import {
makeSchema,
scalarType,
mutationField,
queryField,
arg,
nonNull
} from 'nexus'
import { createServer } from '@graphql-yoga/node'
const FileScalar = scalarType({
name: 'File',
asNexusMethod: 'file',
description: 'The `File` scalar type represents a file upload.',
sourceType: 'File'
})
const greetings = queryField('greetings', {
type: 'String',
resolve: () => 'Hello World!'
})
const readTextFile = mutationField('readTextFile', {
type: 'String',
args: { file: nonNull(arg({ type: 'File' })) },
async resolve(parent, { file }) {
const textContent = await file.text()
return textContent
}
})
const schema = makeSchema({
types: [FileScalar, greetings, readTextFile]
})
const server = createServer({ schema: schema })
// Start the server and explore http://localhost:4000/graphql
server.start()
Disabling Multipart/File Upload Processing
If you want to disable multipart request processing for some reason, you can pass multipart: false
to prevent Yoga from handling multipart requests.
createServer({ multipart: false })
Configuring Multipart Request Processing (only for Node.js)
In Node.js, you can configure the limits of the multipart request processing such as maximum allowed file size, maximum numbers of files, etc.
createServer({
multipart: {
// Maximum allowed file size (in bytes)
fileSize: 1000000,
// Maximum allowed number of files
files: 10,
// Maximum allowed size of content (operations, variables etc...)
fieldSize: 1000000,
// Maximum allowed header size for form data
headerSize: 1000000
}
})