GraphQL Upload

This example has two independent services that are stitched together into a single gateway schema. It uses Schema Extensions to add some local type definitions and resolvers.

This example demonstrates:

  • Adding a remote service that takes a file upload and saves on the disk. It shows how to forwards file uploads to the services through the gateway
  • Adding a remote service that takes an image as a file upload and resizes it by using sharp and returns a base64 string representation of the resized image.
  • It uses File Upload recipe of GraphQL Yoga

Sandbox

⬇️ Click ☰ to see the files

You can also see the project on GitHub here.

The following services are available for interactive queries:

  • Stitched gateway: listening on 4000/graphql
  • Upload Files subservice_: listening on 4001/graphql
  • Resize Images subservice_: listening on 4002/graphql

Summary

Visit the stitched gateway and try running the following query:

query {
  readFile(name: "yoga.png") {
    name
    type
    resizedBase64(width: 720, height: 405)
  }
}

In this example query, readFile of Upload Files subservice is called to read the file from the disk and resizedBase64 of Resize Images subservice is called to resize the image. In our additional resolver we take base64 representation of the file from the Upload Files subservice and pass it to the Resize Images subservice like below;

Created file object is passed to Resize Images as a file upload under the hood;

    resolvers: {
      FileEntry: {
        resizedBase64: {
          // We ask required fields to create a `File` instance
          selectionSet: `{ name type base64 }`,
          resolve(
            { name, type, base64 }: { name: string; type: string; base64: string },
            { width, height },
            context,
            info
          ) {
            if (!type.startsWith('image/')) {
                throw new GraphQLError('File is not an image');
            }
            const buffer = Buffer.from(base64, 'base64');
            const file = new File([buffer], name, { type });
            return delegateToSchema({
              schema: resizeImagesSubschema,
              fieldName: 'resizeImage',
              args: {
                file,
                width,
                height,
              },
              context,
              info,
            });
          },
        },
      },
    },

Upload a File from the gateway

Run the following command from the terminal to upload the file file.txt. To learn more, visit graphql-multipart-request-spec

curl localhost:4000/graphql \
  -F operations='{ "query": "mutation($file: File!) { uploadFile(input: $file) { name type text } }", "variables": { "file": null } }' \
  -F map='{ "0": ["variables.file"] }' \
  -F 0=@graphql-upload/file.txt
 
# output
# {"data":{"uploadFile":{"filename":"file.txt","mimetype":"text/plain","text":"test file but not image\n"}}}