UNPKG

6.13 kBMarkdownView Raw
1# apollo-fetch-upload
2
3[![npm version](https://img.shields.io/npm/v/apollo-fetch-upload.svg)](https://www.npmjs.com/package/apollo-fetch-upload)
4
5Enables the use of [`File`](https://developer.mozilla.org/en/docs/Web/API/File), [`FileList`](https://developer.mozilla.org/en/docs/Web/API/FileList) and [`ReactNativeFile`](#react-native) instances anywhere within mutation or query input variables. With the [`apollo-upload-server`](https://github.com/jaydenseric/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.
6
7Checkout the [example API and client](https://github.com/jaydenseric/apollo-upload-examples).
8
9Use [`apollo-upload-client`](https://github.com/jaydenseric/apollo-upload-client) for earlier versions of [`apollo-client`](https://github.com/apollographql/apollo-client) that do not support an [`apollo-fetch`](https://github.com/apollographql/apollo-fetch) network interface.
10
11## Setup
12
13Install with [npm](https://www.npmjs.com):
14
15```
16npm install apollo-fetch-upload
17```
18
19To setup an [`ApolloClient`](http://dev.apollodata.com/core/apollo-client-api.html#apollo-client) network interface:
20
21```js
22import ApolloClient from 'apollo-client'
23import { createApolloFetchUpload } from 'apollo-fetch-upload'
24import { print } from 'graphql/language/printer'
25
26const apolloFetchUpload = createApolloFetchUpload({
27 uri: 'https://api.githunt.com/graphql'
28})
29
30const ApolloClient = new ApolloClient({
31 networkInterface: {
32 query: request => apolloFetchUpload({
33 ...request,
34 query: print(request.query)
35 })
36 }
37})
38```
39
40Alternatively use query batching:
41
42```js
43import ApolloClient from 'apollo-client'
44import BatchHttpLink from 'apollo-link-batch-http'
45import { createApolloFetchUpload } from 'apollo-fetch-upload'
46
47const ApolloClient = new ApolloClient({
48 networkInterface: new BatchHttpLink({
49 fetch: createApolloFetchUpload({
50 uri: 'https://api.githunt.com/graphql'
51 })
52 })
53})
54```
55
56`createApolloFetchUpload` and `constructUploadOptions` have the same [API](https://github.com/apollographql/apollo-fetch#api) as `createApolloFetch` and `constructDefaultOptions` in [`apollo-fetch`](https://github.com/apollographql/apollo-fetch).
57
58See also the [setup instructions](https://github.com/jaydenseric/apollo-upload-server#setup) for the [`apollo-upload-server`](https://github.com/jaydenseric/apollo-upload-server) middleware.
59
60## Usage
61
62Use [`File`](https://developer.mozilla.org/en/docs/Web/API/File), [`FileList`](https://developer.mozilla.org/en/docs/Web/API/FileList) or [`ReactNativeFile`](#react-native) instances anywhere within mutation or query input variables. For server instructions see [`apollo-upload-server`](https://github.com/jaydenseric/apollo-upload-server). Checkout the [example API and client](https://github.com/jaydenseric/apollo-upload-examples).
63
64### [`File`](https://developer.mozilla.org/en/docs/Web/API/File) example
65
66```jsx
67import { graphql, gql } from 'react-apollo'
68
69const UploadFile = ({ mutate }) => {
70 const handleChange = ({ target }) =>
71 target.validity.valid &&
72 mutate({
73 variables: {
74 file: target.files[0]
75 }
76 })
77
78 return <input type="file" required onChange={handleChange} />
79}
80
81export default graphql(gql`
82 mutation($file: Upload!) {
83 uploadFile(file: $file) {
84 id
85 }
86 }
87`)(UploadFile)
88```
89
90### [`FileList`](https://developer.mozilla.org/en/docs/Web/API/FileList) example
91
92```jsx
93import { graphql, gql } from 'react-apollo'
94
95const UploadFiles = ({ mutate }) => {
96 const handleChange = ({ target }) =>
97 target.validity.valid &&
98 mutate({
99 variables: {
100 files: target.files
101 }
102 })
103
104 return <input type="file" multiple required onChange={handleChange} />
105}
106
107export default graphql(gql`
108 mutation($files: [Upload!]!) {
109 uploadFiles(files: $files) {
110 id
111 }
112 }
113`)(UploadFiles)
114```
115
116### React Native
117
118Substitute [`File`](https://developer.mozilla.org/en/docs/Web/API/File) with `ReactNativeFile` from [`extract-files`](https://github.com/jaydenseric/extract-files):
119
120```js
121import { ReactNativeFile } from 'apollo-fetch-upload'
122
123const variables = {
124 file: new ReactNativeFile({
125 uri: /* Camera roll URI */,
126 type: 'image/jpeg',
127 name: 'photo.jpg'
128 }),
129 files: ReactNativeFile.list([{
130 uri: /* Camera roll URI */,
131 type: 'image/jpeg',
132 name: 'photo-1.jpg'
133 }, {
134 uri: /* Camera roll URI */,
135 type: 'image/jpeg',
136 name: 'photo-2.jpg'
137 }])
138}
139```
140
141## How it works
142
143An ‘operations object’ is a [GraphQL request](http://dev.apollodata.com/tools/graphql-server/requests.html#postRequests) (or array of requests if batching). A ‘file’ is a [`File`](https://developer.mozilla.org/en/docs/Web/API/File) or [`ReactNativeFile`](#react-native) instance.
144
145When an operations object is to be sent to the GraphQL server, any files within are extracted using [`extract-files`](https://github.com/jaydenseric/extract-files), remembering their object paths within request variables.
146
147If no files are extracted a normal fetch with default options happens; the operations object is converted to JSON and sent in the fetch body.
148
149Files must upload as individual multipart form fields. A new [`FormData`](https://developer.mozilla.org/en/docs/Web/API/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.
150
151Multipart GraphQL server requests are handled by [`apollo-upload-server`](https://github.com/jaydenseric/apollo-upload-server) middleware. The files upload to a temp directory, the `operations` field is JSON decoded and [`object-path`](https://github.com/mariocasciaro/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.