'createReadStream is not present in uploaded image

I am using node v14.17.0,"apollo-server-express": "^2.25.0", "graphql-upload": "^12.0.0"

I am trying to upload an image but i dont get createReadStream from the image which i upload from graphiql. I am using Altair graphiql

Here is my 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");
});

In my typedefs i have mentioned

 gql`
      scalar Upload

and my resolvers have

Upload: GraphQLUpload,

I have tried following this issue apollographql/apollo-server#3508 but it doesn't seem to work for me. Downgrading to nodev12 did not help.

My uploaded image contains following

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


Solution 1:[1]

I was able to resolve the error after upgrading to apollo-server v3. I think the v2 was somewhat conflicting with graphql-upload lib

Solution 2:[2]

Below is a single file upload example that uses the graphql-upload and apollo-server-express packages.

Package versions:

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

Nodejs version: v14.16.0.

GraphQL server:

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`));

Send client GraphQL request using Altair graphql.

enter image description here

The logs of the server side, get the createReadStream successfully.

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
}

Upload success:

enter image description here

source code: https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/file-upload

Solution 3:[3]

const { filename, mimetype, createReadStream } = await file.promise;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pritish
Solution 2
Solution 3 Xavier Guihot