From 425849a697d475c70ba496f079d9cc5f46f457b2 Mon Sep 17 00:00:00 2001 From: hantonelli Date: Sun, 31 Mar 2019 18:02:35 +0100 Subject: [PATCH] Improve fileupload example readme. Update scalars.md. Add file-upload.md --- docs/content/reference/file-upload.md | 129 ++++++++++++++++++++++++++ docs/content/reference/scalars.md | 18 +++- example/fileupload/readme.md | 30 +++--- 3 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 docs/content/reference/file-upload.md diff --git a/docs/content/reference/file-upload.md b/docs/content/reference/file-upload.md new file mode 100644 index 00000000000..93f90153947 --- /dev/null +++ b/docs/content/reference/file-upload.md @@ -0,0 +1,129 @@ +--- +title: 'File Upload' +description: How to upload files. +linkTitle: File Upload +menu: { main: { parent: 'reference' } } +--- + +Graphql server has an already build it Upload scalar to upload files using a multipart request. +If follow the following spec https://github.com/jaydenseric/graphql-multipart-request-spec, +that defines a interoperable multipart form field structure for GraphQL requests, used by +various file upload client implementations. + +To use it you add the Upload scalar in you schema, and it will automatically add the marshalling +behaviour to Go types. + +# Examples + +## Single file upload +For this use case, the schema could look like this. + +```graphql +"The `UploadFile, // b.txt` scalar type represents a multipart file upload." +scalar Upload + +"The `Query` type, represents all of the entry points into our object graph." +type Query { + ... +} + +"The `Mutation` type, represents all updates we can make to our data." +type Mutation { + singleUpload(file: Upload!): Bool! +} +``` + +cURL can be use the make a query as follows: +``` +curl localhost:4000/graphql \ + -F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }' \ + -F map='{ "0": ["variables.file"] }' \ + -F 0=@a.txt +``` + +That invokes the following operation: +``` +{ + query: ` + mutation($file: Upload!) { + singleUpload(file: $file) { + id + } + } + `, + variables: { + file: File // a.txt + } +} +``` + +## Multiple file upload +For this use case, the schema could look like this. + +```graphql +"The `Upload` scalar type represents a multipart file upload." +scalar Upload + +"The `File` type, represents the response of uploading a file." +type File { + id: Int! + name: String! + content: String! +} + +"The `UploadFile` type, represents the request for uploading a file with certain payload." +input UploadFile { + id: Int! + file: Upload! +} + +"The `Query` type, represents all of the entry points into our object graph." +type Query { + ... +} + +"The `Mutation` type, represents all updates we can make to our data." +type Mutation { + multipleUpload(req: [UploadFile!]!): [File!]! +} + +``` + +cURL can be use the make a query as follows: + +``` +curl localhost:4000/query \ + -F operations='{ "query": "mutation($req: [UploadFile!]!) { multipleUpload(req: $req) { id, name, content } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }' \ + -F map='{ "0": ["variables.req.0.file"], "1": ["variables.req.1.file"] }' \ + -F 0=@b.txt \ + -F 1=@c.txt +``` + +That invokes the following operation: +``` +{ + query: ` + mutation($req: [UploadFile!]!) + multipleUpload(req: $req) { + id, + name, + content + } + } + `, + variables: { + req: [ + { + id: 1, + File, // b.txt + }, + { + id: 2, + File, // c.txt + } + ] + } +} +``` + +see the [example/fileupload](https://github.com/99designs/gqlgen/tree/master/example/fileupload) package for more examples. diff --git a/docs/content/reference/scalars.md b/docs/content/reference/scalars.md index ec9a9fcf0b6..7b098b06896 100644 --- a/docs/content/reference/scalars.md +++ b/docs/content/reference/scalars.md @@ -7,7 +7,7 @@ menu: { main: { parent: 'reference' } } ## Built-in helpers -gqlgen ships with two built-in helpers for common custom scalar use-cases, `Time` and `Map`. Adding either of these to a schema will automatically add the marshalling behaviour to Go types. +gqlgen ships with three built-in helpers for common custom scalar use-cases, `Time`, `Map` and `Upload`. Adding any of these to a schema will automatically add the marshalling behaviour to Go types. ### Time @@ -25,6 +25,22 @@ scalar Map Maps an arbitrary GraphQL value to a `map[string]{interface}` Go type. + +### Upload + +```graphql +scalar Upload +``` + +Maps a `Upload` GraphQL scalar to a `graphql.Upload` struct, defined as follows: +``` +type Upload struct { + File multipart.File + Filename string + Size int64 +} +``` + ## Custom scalars with user defined types For user defined types you can implement the graphql.Marshal and graphql.Unmarshal interfaces and they will be called. diff --git a/example/fileupload/readme.md b/example/fileupload/readme.md index 3a884f28179..ae0eb4d0950 100644 --- a/example/fileupload/readme.md +++ b/example/fileupload/readme.md @@ -14,7 +14,7 @@ and open http://localhost:8087 in your browser #### Operations -```js +``` { query: ` mutation($file: Upload!) { @@ -61,7 +61,7 @@ Alpha file content. #### Operations -```js +``` { query: ` mutation($file: Upload!) { @@ -109,7 +109,7 @@ Alpha file content. #### Operations -```js +``` { query: ` mutation($files: [Upload!]!) { @@ -167,20 +167,28 @@ Charlie file content. #### Operations -```js +``` { query: ` - mutation($files: [Upload!]!) { - multipleUpload(files: $files) { - id + mutation($req: [UploadFile!]!) + multipleUploadWithPayload(req: $req) { + id, + name, + content } } `, variables: { - files: [ - File, // b.txt - File // c.txt - ] + req: [ + { + id: 1, + File, // b.txt + }, + { + id: 2, + File, // c.txt + } + ] } } ```