如何将图像上传到 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 个依赖项:)
我在 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 客户端上传图片 --
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 个依赖项:)