Отправьте GraphQLUpload в imagekit.io с сервера узлов, на котором работает express-graphql - PullRequest
1 голос
/ 24 октября 2019

Неопытный разработчик здесь. Эта проблема сводит меня с ума.

Я отправляю файл изображения из внешнего интерфейса реакции с помощью мутации graphQL на сервер узлов, на котором выполняется express-graphql. Мутация uploadFile работает правильно, и я могу сохранить файл локально на сервере.

Я хочу загрузить этот файл в imagekit.io, вернуть URL-адрес, а затем отправить URL-адрес клиенту в качестве возврата мутации graqhQL. Я использую пакет imagekit npm и настроил егокак описано в документации API.

В конечном счете, я предпочел бы потоковую передачу файла прямо в imagekit, не сохраняя его на сервере, но я все еще исследую, возможно ли это (совет приветствуется), но это неглавная проблема.

Изображение отправляется с помощью imagekit.upload () в imagekit, и в ответном сообщении говорится, что оно успешно сохранено, однако тип файла «не-изображение» независимо от типа файла (попробовал jpg, png, webp).

Изображение, сохраненное локально на сервере узла, (насколько я могу судить) идентично изображению, отправленному с клиента. Изображение также видно в моей медиатеке imagekit, но неверный размер файла (<100 байт). Эти два наблюдения вместе заставляют меня поверить, что неверная строка отправляется в imagekit, но я не знаю, как правильно ее кодировать</p>

Буду очень признателен за любые указания / помощь, которые может дать каждый.

app.js (сервер)

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

схема. 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 голосов
/ 25 октября 2019

Исправлена ​​проблема после исследования правильного использования 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))
        })

    });
  }
...