• v2
  • Features
  • File Uploads

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:

file-upload-example.ts
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:

nexus-file-upload-example.ts
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
  }
})
Last updated on October 2, 2022