从运行express-graphql的节点服务器将GraphQLUpload发送到imagekit.io

时间:2019-10-24 16:18:34

标签: node.js express graphql express-graphql imagekit

这里没有经验。这个问题使我发疯。

我正在通过graphQL突变将来自反应前端的图像文件发送到运行express-graphql的节点服务器。 uploadFile突变正常运行,并且我能够将文件本地保存在服务器上。

我想将此文件上传到ima​​gekit.io,返回url,然后将其作为graqhQL突变的返回值发送给客户端。我使用的是imagekit npm软件包,并且已按如下所述对其进行了配置api文档。

最终,我宁愿直接将文件流传输到imagekit而不将其保存到服务器,但是我仍在研究这是否可能(建议您多加注意),但这不是主要问题。

图像通过imagekit.upload()发送到imagekit,并且返回消息指出该图像已成功保存,但是无论文件类型如何,文件类型均为“非图像”(尝试jpg,png,webp )。

据我所知,本地保存到节点服务器的图像与从客户端发送的图像相同。该图像在我的imagekit媒体库中也可见,但是文件大小不正确(<100字节)。这两个观察结果共同使我相信错误的字符串被发送到imagekit,但是我不知道如何正确编码。

任何人都可以提供的任何指针/帮助将不胜感激。

app.js(服务器)

import schema from './schema'
...
app.use('/graphql', 
    graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
    graphqlHTTP({
        schema,
        graphiql: true
    })
)
...

schema.js

import {GraphQLUpload} from 'graphql-upload'
...
const Mutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        uploadFile:{
            description: 'Uploads a file',
            type: GraphQLString,
            args: {
                file: {type: new GraphQLNonNull(GraphQLUpload)},
            },
            async resolve(parent, {file}){
                const { filename, mimetype, createReadStream } = await file

            await new Promise(res => 
                createReadStream()
                  .pipe(createWriteStream(path.join(__dirname, "./", filename), {encoding:'base64'}))
                  .on("close", res)

              ).then (                 
                    imagekit.upload({
                        file : path.join(__dirname, "./", filename), //required
                        fileName : filename,   //required

                        }, function(error, result) {

                            if(error) 
                                console.log(error)
                            else {
                                filesArray.push(filename)
                                console.log(result)
                            } 
                        }
                    )  
                )
                return 'Promise that returns the url'
            }
        },

imagekit.upload()的响应:

{
  filePath: '/default-image_ANV6NYo5o.jpg',
  size: 36,
  fileId: '5db1ccc9e954fe57f4c791c9',
  url: 'https://ik.imagekit.io/<My imagekit ID here>/default-image_ANV6NYo5o.jpg',
  name: 'default-image_ANV6NYo5o.jpg',
  fileType: 'non-image'
}

1 个答案:

答案 0 :(得分:0)

研究了fs.createReadStream和Promises的正确使用后,解决了该问题。 仅对流进行编码和发送即可正常工作。

async function encodeFile(file) {
    return new Promise(resolve => {
        let { filename, mimetype, createReadStream } = file

        let encodedFile
        createReadStream()
        .on('data', chunk => {
            encodedFile = chunk.toString('base64')
        })
        .on('close', () => {
            resolve(uploadFile(filename, encodedFile))
        })

    });
  }