apollo-fetch-upload v1.2.0
apollo-fetch-upload
Enables the use of File, FileList and ReactNativeFile instances anywhere within mutation or query input variables. With the apollo-upload-server middleware setup on the GraphQL server, files upload to a configurable temp directory. Upload input type metadata replaces the original files in the arguments received by the resolver.
Checkout the example API and client.
Use apollo-upload-client for earlier versions of apollo-client that do not support an apollo-fetch network interface.
Setup
Install with npm:
npm install apollo-fetch-uploadTo setup an ApolloClient network interface:
import ApolloClient from 'apollo-client'
import { createApolloFetchUpload } from 'apollo-fetch-upload'
import { print } from 'graphql/language/printer'
const apolloFetchUpload = createApolloFetchUpload({
uri: 'https://api.githunt.com/graphql'
})
const ApolloClient = new ApolloClient({
networkInterface: {
query: request => apolloFetchUpload({
...request,
query: print(request.query)
})
}
})Alternatively use query batching:
import ApolloClient from 'apollo-client'
import BatchHttpLink from 'apollo-link-batch-http'
import { createApolloFetchUpload } from 'apollo-fetch-upload'
const ApolloClient = new ApolloClient({
networkInterface: new BatchHttpLink({
fetch: createApolloFetchUpload({
uri: 'https://api.githunt.com/graphql'
})
})
})createApolloFetchUpload and constructUploadOptions have the same API as createApolloFetch and constructDefaultOptions in apollo-fetch.
See also the setup instructions for the apollo-upload-server middleware.
Usage
Use File, FileList or ReactNativeFile instances anywhere within mutation or query input variables. For server instructions see apollo-upload-server. Checkout the example API and client.
File example
import { graphql, gql } from 'react-apollo'
const UploadFile = ({ mutate }) => {
const handleChange = ({ target }) =>
target.validity.valid &&
mutate({
variables: {
file: target.files[0]
}
})
return <input type="file" required onChange={handleChange} />
}
export default graphql(gql`
mutation($file: Upload!) {
uploadFile(file: $file) {
id
}
}
`)(UploadFile)FileList example
import { graphql, gql } from 'react-apollo'
const UploadFiles = ({ mutate }) => {
const handleChange = ({ target }) =>
target.validity.valid &&
mutate({
variables: {
files: target.files
}
})
return <input type="file" multiple required onChange={handleChange} />
}
export default graphql(gql`
mutation($files: [Upload!]!) {
uploadFiles(files: $files) {
id
}
}
`)(UploadFiles)React Native
Substitute File with ReactNativeFile from extract-files:
import { ReactNativeFile } from 'apollo-fetch-upload'
const variables = {
file: new ReactNativeFile({
uri: /* Camera roll URI */,
type: 'image/jpeg',
name: 'photo.jpg'
}),
files: ReactNativeFile.list([{
uri: /* Camera roll URI */,
type: 'image/jpeg',
name: 'photo-1.jpg'
}, {
uri: /* Camera roll URI */,
type: 'image/jpeg',
name: 'photo-2.jpg'
}])
}How it works
An ‘operations object’ is a GraphQL request (or array of requests if batching). A ‘file’ is a File or ReactNativeFile instance.
When an operations object is to be sent to the GraphQL server, any files within are extracted using extract-files, remembering their object paths within request variables.
If no files are extracted a normal fetch with default options happens; the operations object is converted to JSON and sent in the fetch body.
Files must upload as individual multipart form fields. A new FormData form is created and each extracted file is appended as a field named after the file's original operations object path; for example variables.files.0 or 0.variables.files.0 if batching. The operations object (now without files) is converted to JSON and appended as a field named operations. The form is sent in the fetch body.
Multipart GraphQL server requests are handled by apollo-upload-server middleware. The files upload to a temp directory, the operations field is JSON decoded and object-path is used to insert metadata about each of the uploads (including the temp path) in place of the original files in the resolver arguments.