如何将图像上传到 KeystoneJS GraphQL 端点?

How can one upload an image to a KeystoneJS GraphQL endpoint?

我在 KeystoneJS AdminUI 的自定义字段中使用 TinyMCE,这是一个 React 应用程序。我想将图像从 React 前端上传到 KeystoneJS GraphQL 后端。我可以使用添加到 Keystone 服务器的 REST 端点上传图像——向 TinyMCE 传递一个 images_upload_handler 回调——但我想利用 Keystone 已经构建的 GraphQL 端点来处理图像 list/type 我创造了。

我首先尝试使用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 客户端上传图片 -- suggests using apollo-upload-client。但是,我在 KeystoneJS 环境中操作,Apollo-upload-client 说

Apollo Client can only have 1 “terminating” Apollo Link that sends the GraphQL requests; if one such as apollo-link-http is already setup, remove it.

我相信 Keystone 已经设置了 Apollo-link-http(它在搜索中多次出现),所以我认为我不能使用 Apollo-upload-client

UploadLink 只是 HttpLink 的直接替代品。您没有理由不能使用它。有一个演示 KeystoneJS 应用 here 显示了 Apollo Client 配置,包括使用 createUploadLink.

使用 Upload 标量的突变的实际用法显示 here

查看 source code, you should be able to use a custom 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)
    }
  }
})

我以前也遇到过同样的问题,用Apollo上传解决了link。现在,当应用程序进入生产阶段时,我意识到 Apollo 客户端占用了 1/3 的 gzipped 构建文件,我创建了最小的 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 个依赖项:)