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-upload
To 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.
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)
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: ,
type: 'image/jpeg',
name: 'photo.jpg'
}),
files: ReactNativeFile.list([{
uri: ,
type: 'image/jpeg',
name: 'photo-1.jpg'
}, {
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.