GraphQL 如何处理文件上传

阅读时长 7 分钟读完

GraphQL 是一个非常强大的 API 查询语言和运行时,它提供了强类型系统和批量数据查询等特性。GraphQL 同时也提供了扩展性强的语言扩展,让我们可以轻松地在其语言体系内添加我们自己需要的功能。

在实际的应用开发中,上传文件是非常常见的操作。但是,由于 HTTP 协议的限制,文件上传是一个相对复杂的过程,通常需要以 multipart/form-data 的形式传递二进制数据。本文将重点介绍 GraphQL 如何处理文件上传。

传统的文件上传方式

在传统 Web 开发中,文件上传通常使用 form 标签配合 input[type=file] 标签实现。用户完成选择文件之后,提交表单请求。服务器接收到请求之后,会读取用户上传的文件内容,并将其保存到本地磁盘上。在处理文件上传过程中,我们通常需要了解以下几个问题:

  1. 上传文件的大小和类型是否合法;
  2. 如何读取上传的二进制数据;
  3. 如何保存上传的文件;
  4. 如何进行文件校验和处理异常。

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-uploadapollo-server-express。其中:

  • graphql-upload 库提供了我们需要使用的 GraphQLUpload scalar 类型;
  • apollo-server-express 库提供了我们需要用到的 ApolloServergql 对象。

在类型定义中,我们声明了 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 参数来指定给服务器的请求选项,其中包括了 methodbody 两个属性。使用 FormData 打包数据之后,我们可以将其直接传递给 fetchOptions.body 属性。

总结

通过上述示例代码,我们了解到了 GraphQL 如何支持文件上传功能。通过将 GraphQL 查询和变量打包为 multipart/form-data 数据格式,我们可以直接向服务器发送二进制数据。和传统的文件上传方式相比,GraphQL 的文件上传借助于 JSON 和 multipart/form-data 数据格式而更加灵活和高效。

在实际的文件上传操作中,我们通常需要根据具体应用场景,调整服务器端的上传处理逻辑,并处理异常情况。同时,我们也需要合理地配置客户端与服务端之间的传输协议,以提高文件上传的效率和安全性。

如果你在实践过程中遇到了其他问题或觉得本文有待改进,请随时联系作者或在评论区留言。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6465eb85968c7c53b0694f52

纠错
反馈