GraphQL 是一个非常强大的 API 查询语言和运行时,它提供了强类型系统和批量数据查询等特性。GraphQL 同时也提供了扩展性强的语言扩展,让我们可以轻松地在其语言体系内添加我们自己需要的功能。
在实际的应用开发中,上传文件是非常常见的操作。但是,由于 HTTP 协议的限制,文件上传是一个相对复杂的过程,通常需要以 multipart/form-data 的形式传递二进制数据。本文将重点介绍 GraphQL 如何处理文件上传。
传统的文件上传方式
在传统 Web 开发中,文件上传通常使用 form
标签配合 input[type=file]
标签实现。用户完成选择文件之后,提交表单请求。服务器接收到请求之后,会读取用户上传的文件内容,并将其保存到本地磁盘上。在处理文件上传过程中,我们通常需要了解以下几个问题:
- 上传文件的大小和类型是否合法;
- 如何读取上传的二进制数据;
- 如何保存上传的文件;
- 如何进行文件校验和处理异常。
GraphQL 文件上传
与传统的文件上传不同,GraphQL 应用程序通常会使用 JSON 作为请求和响应的格式。但是,JSON 格式并不支持二进制数据的直接传输。那么,如何在 GraphQL 中上传文件呢?
GraphQL 的文件上传依赖于 multipart/form-data 数据格式。在上传文件时,我们需要将 GraphQL 查询和变量一起打包进 multipart/form-data 格式中。同时,文件数据也必须嵌入到 multipart/form-data 格式的数据包中。
运行环境和依赖库
为了运行本文中提到的代码示例,你需要先安装以下环境和依赖库:
- Node.js 环境
- Express Web 服务
- graphql-multipart-request-spec 中间件库
- GraphQL Yoga 库(或其他的 GraphQL 实现)
服务器端代码
以下是一个简单的 GraphQL 文件上传的示例代码:
-- -------------------- ---- ------- ----- ------- - ------------------- ----- - -------------- -------------------- - - -------------------------- ----- - ------------- --- - - --------------------------------- ----- -------- - ---- ------ ------ ---- ----- - ------ ------- - ---- -------- - ------------------ --------- ------- - -- ----- --------- - - ------- -------------- ------ - ------ -- -- ------ ---- ---------- -- --------- - ------------- ----- -------- ----- -- - ----- - ----------------- --------- --------- -------- - - ----- ---------- -- -- --------- ---- --- ---- ------- ---- -- ------ -- -- --- ---- ------ -- -- ------ ----- ------ ---------- ------------- -- -- -- ----- ------ - --- -------------- --------- ---------- --- ----- --- - ---------- -------------------------------- ------------------------ --- --- ------------ ----- ---- -- -- -- --------------- ------ ----- -- -------------------------------------------- --
在上面的示例代码中,我们引入了两个 GraphQL 相关的库,分别是 graphql-upload
和 apollo-server-express
。其中:
graphql-upload
库提供了我们需要使用的GraphQLUpload
scalar 类型;apollo-server-express
库提供了我们需要用到的ApolloServer
和gql
对象。
在类型定义中,我们声明了 Upload
标量类型,并定义了一个名为 singleUpload
的 mutation。
在解析器中,我们将 Upload
标量类型与 graphql-upload
库提供的 GraphQLUpload
scalar 类型绑定起来。
在 singleUpload
中,我们通过解构 args.file
(由 graphql-multipart-request-spec 中间件生成的 Upload
对象)获取到上传的文件流、文件名、MIME 类型和编码等信息,并进行处理。具体处理方法可以根据用户自己的需要进行设置。
客户端代码
以下是一个文件上传的 GraphQL 客户端示例代码:
-- -------------------- ---- ------- ------ - ------------- -------------- --- - ---- ----------------- ------ - ---------------- - ---- ----------------------- ----- ------ - --- -------------- ----- ------------------ ---- -------------------------------- --- ------ --- ---------------- --- ----- -------------------- - ---- -------- ------------------- -------- - ------------------ ------ - -- -- ---- ---------------- ------------ ----------------------------------------------------------------------- ----- --- -- - ----- ---- - ------------------ -- -------- -------- ----- ------- ----- ------------------- ---- ----- ---- - --- ----------- ------------------------- ---------------- ------ --------------------- ---------- - ----- ---- - ---- ------------------ ---------------- ---- ------------------ ---- ---------------- ----- ----------- --- - ----- ------ - ----- --------------- --------- --------------------- ---------- - ---- -- -------- - ------------- - ------- ------- ----- ---- - -- --- ------------------------- - ----- ----- - ------------------- - ---
在上面的代码中,我们使用了 createUploadLink
函数,将 GraphQL 客户端连接到了 GraphQL 服务器。通过创建监听 change
事件的文件选择器,我们可以获取用户选择的文件,并使用 FormData
对象将其打包成 multipart/form-data 格式。
在客户端的 mutate
函数中,我们使用 fetchOptions
参数来指定给服务器的请求选项,其中包括了 method
和 body
两个属性。使用 FormData
打包数据之后,我们可以将其直接传递给 fetchOptions.body
属性。
总结
通过上述示例代码,我们了解到了 GraphQL 如何支持文件上传功能。通过将 GraphQL 查询和变量打包为 multipart/form-data 数据格式,我们可以直接向服务器发送二进制数据。和传统的文件上传方式相比,GraphQL 的文件上传借助于 JSON 和 multipart/form-data 数据格式而更加灵活和高效。
在实际的文件上传操作中,我们通常需要根据具体应用场景,调整服务器端的上传处理逻辑,并处理异常情况。同时,我们也需要合理地配置客户端与服务端之间的传输协议,以提高文件上传的效率和安全性。
如果你在实践过程中遇到了其他问题或觉得本文有待改进,请随时联系作者或在评论区留言。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6465eb85968c7c53b0694f52