如何将图像上传到 KeystoneJS GraphQL 端点?
Posted
技术标签:
【中文标题】如何将图像上传到 KeystoneJS GraphQL 端点?【英文标题】:How can one upload an image to a KeystoneJS GraphQL endpoint? 【发布时间】:2020-06-24 15:48:51 【问题描述】:我在 KeystoneJS AdminUI 的自定义字段中使用 TinyMCE,这是一个 React 应用程序。我想将 React 前端的图像上传到 KeystoneJS GraphQL 后端。我可以使用添加到 Keystone 服务器的 REST 端点上传图像——向 TinyMCE 传递一个images_upload_handler
回调——但我想利用 Keystone 已经构建的 GraphQL 端点来获取图像列表/类型创建的。
我首先尝试使用this article中详述的方法,使用axios
上传图片
const getGQL = (theFile) =>
const query = gql`
mutation upload($file: Upload!)
createImage(file: $file)
id
file
path
filename
`;
// The operation contains the mutation itself as "query"
// and the variables that are associated with the arguments
// The file variable is null because we can only pass text
// in operation variables
const operation =
query,
variables:
file: null
;
// This map is used to associate the file saved in the body
// of the request under "0" with the operation variable "variables.file"
const map =
'0': ['variables.file']
;
// This is the body of the request
// the FormData constructor builds a multipart/form-data request body
// Here we add the operation, map, and file to upload
const body = new FormData();
body.append('operations', JSON.stringify(operation));
body.append('map', JSON.stringify(map));
body.append('0', theFile);
// Create the options of our POST request
const opts =
method: 'post',
url: 'http://localhost:4545/admin/api',
body
;
// @ts-ignore
return axios(opts);
;
但我不确定要传递什么 theFile
-- TinyMCE 的 images_upload_handler
,我需要从中调用图像上传,接受一个 blobInfo
对象,其中包含给我的功能
文件名不起作用,blob 也不起作用——两者都给我服务器错误 500——错误消息没有更具体。
我更喜欢使用 GraphQL 客户端来上传图片——another SO article 建议使用apollo-upload-client。但是,我在 KeystoneJS 环境中操作,Apollo-upload-client 说
Apollo 客户端只能有 1 个“终止”Apollo Link 发送 GraphQL 请求;如果已经设置了诸如 apollo-link-http 之类的, 删除它。
我相信 Keystone 已经设置了Apollo-link-http
(它在搜索中多次出现),所以我认为我不能使用Apollo-upload-client
。
【问题讨论】:
【参考方案1】:UploadLink
只是 HttpLink
的替代品。你没有理由不能使用它。有一个演示 KeystoneJS 应用程序 here,它显示了 Apollo 客户端配置,包括使用 createUploadLink
。
带有Upload
标量的突变的实际用法显示为here。
查看source code,您应该能够使用自定义image handler 并在提供的blobInfo
对象上调用blob
。像这样的:
tinymce.init(
images_upload_handler: async function (blobInfo, success, failure)
const image = blobInfo.blob()
try
await apolloClient.mutate(
gql` mutation($image: Upload!) ... `,
variables: image
)
success()
catch (e)
failure(e)
)
【讨论】:
我是 GraphQL 的相对新手——当你说“直接替换”时,我具体用UploadLink
做什么?他们的文档说要删除已设置的任何其他“终止链接”。我真的需要这样做吗?在 Keystone 的背景下,如何? - 此外,您链接的示例非常有帮助,但由于我在受限上下文中操作,我只提供文件名、blob 等内容(如上所述),我如何使用它来到达示例正在使用的 File 对象(从表单中获取)?
通常,您使用 HttpLink like this。您无需创建 HttpLink,而是创建 UploadLink,如 here 所示。
我会仔细研究所有内容。我的一个问题是,当我在 AdminUI 中工作时,是否会发生任何变化?也就是说,看演示——github.com/keystonejs/keystone/blob/…——它似乎是从头开始设置 Apollo 客户端,但在 AdminUI 中已经完成了所有工作。我应该再做一次,即设置我自己的“本地”Apollo 客户端吗?还是我误会了什么?
@DanielRearden 结果怎么样 - blob 不应该被替换为从突变返回的远程 url 生成的新的?
我对 KeystoneJS 不是很熟悉,但它看起来像管理应用程序already uses createUploadLink【参考方案2】:
我以前也有同样的问题,用 Apollo 上传链接解决了。现在,当应用程序进入生产阶段时,我意识到 Apollo 客户端占用了 1/3 的 gzip 压缩构建文件,我创建了最小的 graphql 客户端,仅用于自动上传图像的 keystone。该软件包在 npm 中可用:https://www.npmjs.com/package/@sylchi/keystone-graphql-client
如果有用户将头像字段设置为文件,则将 github 徽标上传到用户配置文件的使用示例:
import mutate from '@sylchi/keystone-graphql-client'
const getFile = () => fetch('https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png',
mode: "cors",
cache: "no-cache"
)
.then(response => response.blob())
.then(blob =>
return new File([blob], "file.png", type: "image/png" )
);
getFile().then(file =>
const options =
mutation: `
mutation($id: ID!, $data: UserUpdateInput!)
updateUser(id: $id, data: $data)
id
`,
variables:
id: "5f5a7f712a64d9db72b30602", //replace with user id
data:
avatar: file
mutate(options).then(result => console.log(result));
);
整个包只有 50loc 和 1 个依赖 :)
【讨论】:
以上是关于如何将图像上传到 KeystoneJS GraphQL 端点?的主要内容,如果未能解决你的问题,请参考以下文章
如何将图片从 TinyMCE 上传到 Apollo GraphQL 服务器?
Microsoft Graph API - 如何将附件上传到列表项
如何使用 iPhone 中的 Graph API 在 Facebook 上上传照片?