Apollo GraphQL File Upload Link
raw JSON →apollo-upload-client is a terminating Apollo Link for Apollo Client that facilitates file uploads within GraphQL mutations using the GraphQL multipart request specification. It automatically detects `FileList`, `File`, or `Blob` instances in GraphQL variables and constructs a multipart request, falling back to a standard GraphQL POST or GET request otherwise. The current stable version is 19.0.0, with major versions released somewhat frequently to align with `@apollo/client` updates and Node.js LTS changes. Its primary differentiator is seamless integration with Apollo Client for file uploads, abstracting the multipart request complexity, and adhering to the community-standard GraphQL multipart request specification. It requires a compatible server-side implementation that also follows the specification.
Common errors
error Error: Cannot find module '@apollo/client' ↓
npm install @apollo/client or yarn add @apollo/client. error TypeError: Cannot read properties of undefined (reading 'files') or related file upload issues. ↓
graphql-multipart-request-spec and that your resolvers are correctly processing the Upload scalar. error Error: Link is not a function or related Apollo Link initialization errors. ↓
import { createUploadLink } from 'apollo-upload-client'; and that your @apollo/client version matches the peer dependency requirements. error SyntaxError: Named export 'createUploadLink' not found. The requested module 'apollo-upload-client' does not provide an export named 'createUploadLink' ↓
import/export) or is transpiled correctly. For Node.js, confirm type: module in package.json or use .mjs files. Warnings
breaking Node.js support has been tightened. Version 19.0.0 requires `^20.9.0 || >=22.0.0`. Older versions required different Node.js ranges. ↓
breaking The `@apollo/client` peer dependency was updated to `^4.0.0` in v19.0.0 and `^3.8.0` in v18.0.0. Mismatching versions can lead to runtime errors or unexpected behavior. ↓
breaking React Native is no longer supported out of the box since v18.0.0. The `ReactNativeFile` class is no longer exported or matched by `isExtractableFile`. ↓
breaking A new peer dependency `rxjs` at `^7.3.0` was added in v19.0.0, as it is a requirement for `@apollo/client` v4. ↓
breaking The package moved from `@apollo/client` as a direct dependency to a peer dependency in v15.0.0. This change requires developers to explicitly install `@apollo/client` themselves. ↓
gotcha This library is a 'terminating link'. Apollo Client can only have one terminating link. If you're already using `HttpLink`, you must replace it with `createUploadLink`. ↓
Install
npm install apollo-upload-client yarn add apollo-upload-client pnpm add apollo-upload-client Imports
- createUploadLink wrong
const createUploadLink = require('apollo-upload-client').createUploadLink;correctimport { createUploadLink } from 'apollo-upload-client'; - UploadHttpLink wrong
import UploadHttpLink from 'apollo-upload-client/UploadHttpLink';correctimport { UploadHttpLink } from 'apollo-upload-client'; - ApolloClient
import { ApolloClient, InMemoryCache } from '@apollo/client';
Quickstart
import { ApolloClient, InMemoryCache, gql, ApolloProvider } from '@apollo/client';
import { createUploadLink } from 'apollo-upload-client';
import React from 'react';
import { useMutation } from '@apollo/client/react';
// Configure the Apollo Client with the upload link
const uploadLink = createUploadLink({
uri: 'http://localhost:4000/graphql', // Replace with your GraphQL server endpoint
});
const client = new ApolloClient({
cache: new InMemoryCache(),
link: uploadLink,
});
// GraphQL mutation definition for file upload
const UPLOAD_FILE_MUTATION = gql`
mutation uploadFile($file: Upload!) {
uploadFile(file: $file) {
filename
mimetype
encoding
success
}
}
`;
/** React component for uploading a single file. */
function UploadFileComponent() {
const [uploadFile, { loading, error, data }] = useMutation(UPLOAD_FILE_MUTATION);
const handleFileChange = ({ target: { validity, files } }) => {
if (validity.valid && files && files[0]) {
uploadFile({
variables: {
file: files[0],
},
});
}
};
return (
<div>
<input type="file" required onChange={handleFileChange} />
{loading && <p>Uploading...</p>}
{error && <p>Error: {error.message}</p>}
{data && <p>Upload successful: {data.uploadFile.filename}</p>}
</div>
);
}
// Root component to provide Apollo Client context
function App() {
return (
<ApolloProvider client={client}>
<h1>File Upload Example</h1>
<UploadFileComponent />
</ApolloProvider>
);
}
export default App;