by Lucas McGartland
卢卡斯·麦加兰(Lucas McGartland)
GraphQL is an amazing way to query and manipulate data. You describe your data, ask for what you want, and get predictable results. The problem is, GraphQL only handles serializable data out of the box—there’s no way to upload files directly as part of your mutations.
GraphQL是一种查询和处理数据的绝佳方法。 您描述您的数据,询问您想要什么,并获得可预测的结果。 问题是,GraphQL仅处理开箱即用的可序列化数据,无法作为突变的一部分直接上传文件。
But what if there were a way to combine the power of GraphQL with the ease of uploading files in a multi-part request? @jaydenseric has come up with a solution: graphql-multipart-request-spec
但是,如果有一种方法可以将GraphQL的功能与在多部分请求中轻松上传文件相结合? @jaydenseric提出了一个解决方案: graphql-multipart-request-spec
If you just want the code to make this work, jump to the end of this article to find JavaScript and Python implementations of the spec for Apollo and Graphene.
如果您只是想让代码完成这项工作,请跳到本文结尾,以找到Apollo和Graphene规范JavaScript和Python实现。
Vanilla GraphQL doesn’t support throwing raw files into your mutations. The data you can request and manipulate is limited to what you can serialize over the network. In practice, this looks like basic types: numbers, booleans, and strings. These work great—you can build almost everything you need with basic data types.
Vanilla GraphQL不支持将原始文件放入突变中。 您可以请求和处理的数据仅限于可以通过网络序列化的数据。 实际上,这看起来像基本类型: 数字,布尔值和字符串 。 这些功能非常好-您可以使用基本数据类型构建几乎所有您需要的东西。
But what if you need to run a mutation that takes a file as an argument? For example: uploading a new profile picture. Here’s how you could deal with the problem with ordinary GraphQL:
但是,如果您需要运行一个以文件作为参数的突变,该怎么办? 例如:上传新的个人资料图片。 这是使用普通GraphQL处理问题的方法:
Base64 encode the image and send it over the wire as a string in your mutation. This has several disadvatanges:
Base64对图像进行编码,然后将其作为字符串发送给您的突变。 这有几个缺点:
Run a seperate server (or API) for uploading files. Upload the file in the first request, and then pass the resulting storage URL as part of your mutation (the second request).
运行单独的服务器(或API)以上传文件。 在第一个请求中上传文件,然后将生成的存储URL作为您的更改的一部分(第二个请求)传递。
However if you have to upload several files, you would have to wait until all the uploads are done before you could pass the URLs (to identify them) in your mutation, forcing a synchronous and slow process. It also adds another layer of complexity to make it handle all these requests separately in your client.
但是,如果必须上载多个文件,则必须等到所有上载完成后,才能在突变中传递URL(以识别它们),从而强制执行同步且缓慢的过程。 它还增加了另一层复杂性,使其可以在客户端中分别处理所有这些请求。
Wouldn’t it be cool to just pass a file in as part of the mutation parameters?
仅将文件作为突变参数的一部分传递会很酷吗?
This is where the multipart request spec comes in. This GraphQL extension specification allows you to nest files anywhere within GraphQL mutations like this:
这是多部分请求规范的来源。此GraphQL扩展规范允许您在GraphQL突变内的任何位置嵌套文件,如下所示:
{ query: ` mutation($file: Upload!) { uploadFile(file: $file) { id } } `, variables: { file: File // somefile.jpg }}
As you can see, adding in a file is as simple as adding in any other type of mutation parameter. To implement this spec, you have to install two parts: one that runs on the client, and another that runs on the server. Here’s what they do:
如您所见,添加文件就像添加任何其他类型的mutation参数一样简单。 要实现此规范,您必须安装两部分:一部分在客户端上运行,另一部分在服务器上运行。 他们的工作如下:
So in apollo-client, you can run a mutation that looks like this:
因此,在apollo客户端中,您可以运行如下所示的突变:
this.props.mutate({variables: {file: yourFile}})
If you’re looking to implement the multipart request spec with Apollo, you can easily integrate it with these packages written by Jayden Seric. These are for the JavaScript and Apollo ecosystem.
如果您希望通过Apollo实现多部分请求规范,则可以轻松地将其与Jayden Seric编写的这些软件包集成。 这些是针对JavaScript和Apollo生态系统的。
jaydenseric/apollo-upload-clientapollo-upload-client - Enhances Apollo Client for intuitive file uploads via GraphQL mutations.github.comjaydenseric/apollo-upload-serverapollo-upload-server - Enhances Apollo GraphQL Server for intuitive file uploads via GraphQL mutations.github.com
jaydenseric / apollo上载客户端 apollo上载客户端-增强了Apollo客户端,可通过GraphQL突变直观地上传文件。 github.com jaydenseric / apollo-upload-server apollo-upload-server-增强了Apollo GraphQL Server,可通过GraphQL突变直观地上传文件。 github.com
If you run your GraphQL API through Graphene and Django, you can implement the spec in Python by replacing your GraphQL view with this package I wrote here:
如果通过Graphene和Django运行GraphQL API,则可以通过用我在此处编写的此程序包替换GraphQL视图,从而在Python中实现该规范:
lmcgartland/graphene-file-uploadgraphene-file-upload - Enhances Graphene Django GraphQL Server for intuitive file uploads via GraphQL mutations.github.com
lmcgartland / graphene-file-upload graphene-file-upload-增强了Graphene Django GraphQL Server,可通过GraphQL突变直观地上传文件。 github.com
This spec is an easy way to add file upload capability to your GraphQL application. Focus less on how to get your files, and more on what you get to do with them!
该规范是向GraphQL应用程序添加文件上传功能的简便方法。 少集中精力于如何获取文件,而更多地关注与文件的关系!
If you want to talk more, chat about GraphQL or great typefaces, hit me up on twitter @lucasmcgartland. Or find me elsewhere on the web below:
如果您想谈论更多内容,请聊聊GraphQL或出色的字体,请在twitter @ lucasmcgartland上打我。 或在下面的网上其他地方找到我:
https://medium.com/@danielbuechele/file-uploads-with-graphql-and-apollo-5502bbf3941e
https://medium.com/@danielbuechele/file-uploads-with-graphql-and-apollo-5502bbf3941e