Enhances Apollo for intuitive file uploads via GraphQL queries or mutations. Use with a GraphQL multipart request spec server implementation such as apollo-upload-server.
Install with peer dependencies using npm:
npm install apollo-upload-client apollo-link
Initialize Apollo Client with this terminating link:
import { createUploadLink } from 'apollo-upload-client'
const link = createUploadLink(/* Options */)
createUploadLink
options match createHttpLink
options:
includeExtensions
(boolean): Toggles sendingextensions
fields to the GraphQL server. (default:false
).uri
(string): GraphQL endpoint URI (default:/graphql
).credentials
(string): OverridesfetchOptions.credentials
.headers
(object): Merges with and overridesfetchOptions.headers
.fetchOptions
(object):fetch
init; overridden by upload requirements.fetch
(function): Fetch API to use (default: Globalfetch
).
Use FileList
, File
, Blob
or ReactNativeFile
instances anywhere within query or mutation input variables to send a GraphQL multipart request. See also apollo-upload-server usage and the example API and client.
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
export default graphql(gql`
mutation($files: [Upload!]!) {
uploadFiles(files: $files) {
id
}
}
`)(({ mutate }) => (
<input
type="file"
multiple
required
onChange={({ target: { validity, files } }) =>
validity.valid && mutate({ variables: { files } })
}
/>
))
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
export default graphql(gql`
mutation($file: Upload!) {
uploadFile(file: $file) {
id
}
}
`)(({ mutate }) => (
<input
type="file"
required
onChange={({ target: { validity, files: [file] } }) =>
validity.valid && mutate({ variables: { file } })
}
/>
))
import gql from 'graphql-tag'
// Apollo Client instance
import client from './apollo'
const file = new Blob(['Foo.'], { type: 'text/plain' })
// Optional, defaults to `blob`
file.name = 'bar.txt'
client.mutate({
mutation: gql`
mutation($file: Upload!) {
uploadFile(file: $file) {
id
}
}
`,
variables: { file }
})
Substitute File
with ReactNativeFile
from extract-files
:
import { ReactNativeFile } from 'apollo-upload-client'
const file = new ReactNativeFile({
uri: '…',
type: 'image/jpeg',
name: 'photo.jpg'
})
const files = ReactNativeFile.list([
{
uri: '…',
type: 'image/jpeg',
name: 'photo-1.jpg'
},
{
uri: '…',
type: 'image/jpeg',
name: 'photo-2.jpg'
}
])
The main difference between using apollo-upload-client in a browser vs server environment is that in the server version you need to provide a function that replaces FormData
which is native to any browser. The createUploadLink
function receives the param serverFormData
to that end. We suggest you use the npm package forma-data
as you can see in the example bellow.
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { createUploadLink } from 'apollo-upload-client'
import gql from 'graphql-tag'
import fs from 'fs'
import fetch from 'node-fetch'
import FormData from 'form-data'
const client = new ApolloClient({
link: createUploadLink({
uri: 'https://example.server.com/graphql',
serverFormData: FormData,
fetch
}),
cache: new InMemoryCache()
})
const variables = {
file: fs.createReadStream('/path/to/file')
}
const mutation = gql`
mutation UploadFile($file: Upload!) {
uploadFile(file: $file) {
id
}
}
`
client.mutate({ mutation, variables })
This will eventually be supported by mergeSchemas
function, but at this point this is a solution.
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { createUploadLink } from 'apollo-upload-client'
import { mergeSchemas } from 'graphql-tools'
import gql from 'graphql-tag'
import fetch from 'node-fetch'
import FormData from 'form-data'
mergeSchemas({
schemas: [bookSchema, authorSchema],
resolvers: mergeInfo => ({
Mutation: {
async uploadBook(parent, args, context, info){
const client = new ApolloClient({
link: createUploadLink({
uri: 'https://book.microservice.com/graphql',
serverFormData: FormData,
fetch
}),
cache: new InMemoryCache()
})
return await client.mutate({
// if you add 'request' in your context by default
// you can:
mutation: gql(context.request.body.query),
variables: args
})
}
}
}
}
- Node.js v6.10+, see
package.json
engines
. - Browsers >1% usage, see
package.json
browserslist
. - React Native.