GraphQL 是一种用于 API 的查询语言和运行时环境,它可以轻松地处理复杂的数据关系和查询。但是,当我们需要在 GraphQL 中实现文件上传和下载时,可能会遇到一些挑战。本文将介绍如何在 GraphQL 中实现文件上传和下载,并提供示例代码。
文件上传
在 GraphQL 中实现文件上传需要使用 GraphQLUpload 类型。这个类型是由 graphql-upload 库提供的,它是一个用于处理文件上传的 GraphQL 扩展。
安装 graphql-upload
首先,我们需要安装 graphql-upload 库:
npm install graphql-upload
在 schema 中定义上传类型
接下来,我们需要在 schema 中定义上传类型。使用 GraphQLUpload 类型,我们可以定义一个 Upload 类型,它表示上传的文件。
scalar Upload
type Mutation {
uploadFile(file: Upload!): Boolean
}实现文件上传的 resolver
现在,我们需要实现一个 resolver 来处理文件上传。我们可以使用 createReadStream 方法来读取上传的文件,并将其保存到服务器上。
-- -------------------- ---- -------
----- - ----------------- - - --------------
----- - ---------------- - - --------------
----- - ------------- - - --------------------------
----- --------- - -
--------- -
----------- ----- -------- - ---- -- -- -
----- - ----------------- -------- - - ----- -----
----- ------ - -------------------
----- ---- - -----------------------------------
------ --- ----------------- ------- --
------
------------------------------
------------- -- -- --------------
------------ -- -- --------------
--
--
--
------- --------------
--
-------------- - ----------这个 resolver 接受一个 file 参数,使用 createReadStream 方法读取上传的文件,并将其保存到服务器上。最后,它返回一个 Promise,如果文件上传成功,则 Promise 将被解析为 true,否则将被拒绝为 false。
在客户端上传文件
现在,我们已经在服务器上实现了文件上传,我们需要在客户端上实现上传文件的功能。我们可以使用 fetch 方法来发送一个 multipart/form-data 请求,并将上传的文件作为 FormData 对象发送。
-- -------------------- ---- -------
----- --------- - --------------------------------------
------------------------------------ ----- -- -- -
----- ---- - -------------------
----- -------- - --- -----------
----------------------- ------
----- -------- - ----- ----------------- -
------- -------
-------- -
------- -------------------
--
----- ---------
---
----- ------ - ----- ----------------
--------------------
---这个代码片段监听一个 <input type="file"> 元素的变化事件,当用户选择一个文件时,它将使用 fetch 方法将文件上传到服务器。注意,我们需要将请求的 Content-Type 设置为 multipart/form-data。
文件下载
在 GraphQL 中实现文件下载需要使用 GraphQLScalarType 类型。这个类型是由 GraphQL 原生提供的,它可以表示任何标量值。
在 schema 中定义下载类型
首先,我们需要在 schema 中定义下载类型。使用 GraphQLScalarType 类型,我们可以定义一个 Download 类型,它表示下载的文件。
scalar Download
type Query {
downloadFile(filename: String!): Download
}实现文件下载的 resolver
现在,我们需要实现一个 resolver 来处理文件下载。我们可以使用 createReadStream 方法来读取服务器上的文件,并将其作为响应的一部分发送给客户端。
-- -------------------- ---- -------
----- - ---------------- - - --------------
----- - ----------------- - - -------------------
----- --------- - -
------ -
------------- -------- - -------- -- -------- ----- -- -
----- ---- - -----------------------------------
----- ------ - -----------------------
------ --- ----------------- ------- -- -
----- ------ - ---
----------------- ----- -- --------------------
------------------ ----- -- ---------------
---------------- -- -- -
----- ------ - ----------------------
-----------------------------------
---
---
--
--
--------- --- -------------------
----- -----------
------------ ---- ---------- ------ ---- ---------- - -------------- -------
----------- ----- -- ------
---------- ----- -- ------
------------- --- -- ----------
---
--
-------------- - ----------这个 resolver 接受一个 filename 参数,使用 createReadStream 方法读取服务器上的文件,并将其作为响应的一部分发送给客户端。最后,它返回一个 Promise,Promise 将被解析为一个 base64 编码的字符串,表示下载的文件。
在客户端下载文件
现在,我们已经在服务器上实现了文件下载,我们需要在客户端上实现下载文件的功能。我们可以使用 fetch 方法来发送一个请求,并将响应的 base64 编码字符串解码为一个二进制文件。
-- -------------------- ---- ------- ----- -------------- - ------------------------------------------- ---------------------------------------- ----- -- -- - ----- -------- - ----------- ----- -------- - ----- --------------------------------------------------------------- ----- ------ - ----- ---------------- ----- ----------- - ------------------------------- ----- ---- - --- ------------------- - ----- ------------ --- ----- --- - -------------------------- ----- ---- - ---------------------------- --------- - ---- ------------- - --------- ------------- ---
这个代码片段创建一个 <a> 元素,当用户点击一个按钮时,它将使用 fetch 方法从服务器下载文件。注意,我们需要将查询字符串包含在 URL 中,并将响应的 base64 编码字符串解码为一个二进制文件。最后,我们使用 createObjectURL 方法创建一个 URL,将其作为下载链接的 href 属性,并模拟点击下载链接。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/67d8f145a941bf7134054a21