createReadStream отсутствует в загруженном изображении

#javascript #node.js #express #graphql #apollo-server

Вопрос:

Я использую node v14.17.0,"apollo-server-express": "^2.25.0", "graphql-upload": "^12.0.0"

Я пытаюсь загрузить изображение, но я не получаю createReadStream от изображения, с которого я загружаю graphiql . Я использую Altair graphiql

Вот мой index.js

 const app = express();

app.use(
  graphqlUploadExpress({
    maxFileSize: 30000000,
    maxFiles: 20,
  })
);

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: contextMiddleware,
  uploads: false,
});


server.applyMiddleware({ app });

app.listen(PORT, () => {
  console.log("Success");
});
 

В своем typedefs я уже упоминал

  gql`
      scalar Upload
 

и мои решатели имеют

 Upload: GraphQLUpload,
 

Я пытался решить эту проблему apollographql/apollo-server#3508 , но, похоже, это не работает для меня. Понижение рейтинга до nodev12 не помогло.

Мое загруженное изображение содержит следующее

 {"filename":"download123.jpg","mimetype":"image/jpeg","encoding":"7bit"}
 

Ответ №1:

Ниже приведен пример загрузки одного файла, в котором используются graphql-upload apollo-server-express пакеты и.

Версии пакетов:

 "apollo-server-express": "^2.15.1",
"graphql-upload": "^12.0.0",
"graphql": "^14.6.0",
 

Версия Nodejs: v14.16.0 .

Сервер GraphQL:

 import { ApolloServer, gql } from 'apollo-server-express';
import express from 'express';
import path from 'path';
import { createWriteStream, unlink } from 'fs';
import { graphqlUploadExpress } from 'graphql-upload';

const app = express();
const PORT = 3000;
const UPLOAD_DIR = path.resolve(__dirname, './uploads');

const typeDefs = gql`
  scalar Upload
  type Query {
    dummy: String
  }
  type Mutation {
    upload(upload: Upload!): Boolean
  }
`;

const resolvers = {
  Query: {},
  Mutation: {
    async upload(_, { upload }) {
      const { file } = upload;
      const { filename, mimetype, createReadStream } = await file;
      const stream = createReadStream();
      const id = Date.now();
      const uploadPath = `${UPLOAD_DIR}/${id}-${filename}`;
      console.log(filename, mimetype, createReadStream, stream);

      await new Promise((resolve, reject) => {
        const writeStream = createWriteStream(uploadPath);
        writeStream.on('finish', resolve);
        writeStream.on('error', (error) => {
          unlink(uploadPath, () => {
            reject(error);
          });
        });
        stream.on('error', (error) => writeStream.destroy(error));
        stream.pipe(writeStream);
      });

      return true;
    },
  },
};

app.use(
  graphqlUploadExpress({
    maxFileSize: 30000000,
    maxFiles: 20,
  }),
);

const server = new ApolloServer({
  typeDefs,
  resolvers,
  uploads: false,
});

server.applyMiddleware({ app });

app.listen(PORT, () => console.log(`GraphQL server is listening on http://localhost:${PORT}/graphql`));
 

Отправьте клиентский запрос GraphQL с помощью Altair graphql.

введите описание изображения здесь

Журналы на стороне сервера, получите createReadStream успешно.

 GraphQL server is listening on http://localhost:3000/graphql
matej-sefcik-GCRbVZydPT4-unsplash.jpg image/jpeg [Function: createReadStream] <ref *1> ReadStream {
  _readableState: ReadableState {
    objectMode: false,
    highWaterMark: 16384,
    buffer: BufferList { head: null, tail: null, length: 0 },
    length: 0,
    pipes: [],
    flowing: null,
    ended: false,
    endEmitted: false,
    reading: false,
    sync: true,
    needReadable: false,
    emittedReadable: false,
    readableListening: false,
    resumeScheduled: false,
    errorEmitted: false,
    emitClose: true,
    autoDestroy: true,
    destroyed: false,
    errored: null,
    closed: false,
    closeEmitted: false,
    defaultEncoding: 'utf8',
    awaitDrainWriters: null,
    multiAwaitDrain: false,
    readingMore: false,
    decoder: null,
    encoding: null,
    [Symbol(kPaused)]: null
  },
  _events: [Object: null prototype] { close: [Function: remove] },
  _eventsCount: 1,
  _maxListeners: undefined,
  _pos: 0,
  _writeStream: WriteStream {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: true,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 63781,
      writing: true,
      corked: 0,
      sync: false,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: [Function: nop],
      writelen: 63781,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 1,
      prefinished: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: false,
      errored: null,
      closed: false
    },
    _events: [Object: null prototype] {
      error: [Array],
      unpipe: [Function: onunpipe],
      close: [Function],
      finish: [Function],
      ready: [Function],
      drain: [Function: pipeOnDrainFunctionResult]
    },
    _eventsCount: 6,
    _maxListeners: undefined,
    _fd: null,
    _path: null,
    _pos: 0,
    _readStreams: Set(1) { [Circular *1] },
    _released: false,
    _cleanupSync: [Function (anonymous)],
    [Symbol(kCapture)]: false
  },
  [Symbol(kCapture)]: false
}
 

Успешная загрузка:

введите описание изображения здесь

исходный код: https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/file-upload

Комментарии:

1. это отличается от [обычного, хорошо известного] github.com/jaydenseric/graphql-upload#examples обработка аргументов — дополнительный уровень внутри переменной file / upload arg?

2. @xadm Я знаю этот пример. Но это правда file , что поле внутри upload аргумента в этом примере. Я добавил ссылку на свой исходный код, проверьте ее.

3. @slideshowp2 У меня возникает проблема с этой строкой const { имя файла, mimetype, createReadStream } = файл ожидания; не удается уничтожить свойство «имя файла «» (промежуточное значение)», поскольку оно не определено. Я думаю, что xadm прав, это не так, как graphql-upload обрабатывает загрузку

4. @Pritish Похоже, я столкнулся с этой проблемой .

5. @slideshowp2 Я поднял ту же проблему при загрузке graphql, но автор закрыл ее, сказав, что проблема со стороны apollo-сервера

Ответ №2:

Я смог устранить ошибку после обновления до apollo-server v3 . Я думаю v2 , что это несколько противоречило graphql-upload либ