上传的图像中不存在 createReadStream

createReadStream is not present in uploaded image

我正在使用node v14.17.0,"apollo-server-express": "^2.25.0", "graphql-upload": "^12.0.0"

我正在尝试上传图片,但我从 graphiql 上传的图片中没有得到 createReadStream。我正在使用 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"}

下面是使用 graphql-uploadapollo-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`));

使用 Altair graphql 发送客户端 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

升级到 apollo-server v3 后我能够解决错误。我认为 v2graphql-upload lib

有点冲突
const { filename, mimetype, createReadStream } = await file.promise;