How to save filestream as a file in a folder in node

10,642

Solution 1

This is the code that worked for me. I'm using Apollo Server and Graphql and 'singleUpload' is the resolver I created for uploading an image.

const path = require("path");
const { createWriteStream } = require("fs");

Both these imports are already included in the node package so you don't need to install them separately.

singleUpload: async (_, { file }) => {
      const { createReadStream, filename, mimetype, encoding } = await file;

      await new Promise((res) =>
        createReadStream()
          .pipe(
            createWriteStream(
              path.join(__dirname, "../../uploads/images", filename)
            )
          )
          .on("close", res)
      );

      return true;
    }
  }
};

The 'file' is the image file I forwarded from <input type="file"/>. The apollo-upload-client in the front-end automatically stores the stream in the 'createReadStream()' that I can destructure form the incoming file promise. I then pipe that stream using 'createWriteStream' and store it in the path I specify on my server. The path within the createWriteStream function is relative to your current directory and the server will look for this folder during runtime, so make sure it exists.

One last thing, if you're serving these images to the front-end directly from the server, make sure to include the line below in your main index.js server file.

app.use("/images", express.static(path.join(__dirname, "./uploads/images")));

Solution 2

I was helped by the apollo-upload-server author regarding this issue. Just in case someone would encounter this issue, here is how to save the stream to a file:

const storeFS = ({ stream, filename }) => {
  const uploadDir = './uploads';
  const path = `${uploadDir}/${filename}`;
  return new Promise((resolve, reject) =>
    stream
      .on('error', error => {
        if (stream.truncated)
          // delete the truncated file
          fs.unlinkSync(path);
        reject(error);
      })
      .pipe(fs.createWriteStream(path))
      .on('error', error => reject(error))
      .on('finish', () => resolve({ path }))
  );
}

Source: https://github.com/jaydenseric/apollo-upload-examples/blob/master/api/resolvers.mjs#L18

Share:
10,642

Related videos on Youtube

Woppi
Author by

Woppi

Updated on June 04, 2022

Comments

  • Woppi
    Woppi almost 2 years

    When I upload a file, the server is returning a stream, filename, mimetype, encoding. I can't figure out how to save the stream as a file in my server. I tried fs.createReadStream, I just can't figure out the next steps for it like how do I put it in ./uploads folder?

     { stream:
      FileStream {
        _readableState: [Object],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        truncated: false,
        _read: [Function] },
     filename: 'test-sample.xlsx',
     mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
     encoding: '7bit' } }
    
  • Alexander Kachkaev
    Alexander Kachkaev over 5 years
    Using stream produces DeprecationWarning: File upload property ‘stream’ is deprecated. Use ‘createReadStream()’ instead. The solution is to use { createReadStream, filename } and createReadStream().on(...). Source: github.com/apollographql/apollo-server/issues/…
  • kubido
    kubido over 5 years
    Hi, I try the code above.. and my file is always return this error message: Request disconnected during file upload stream parsing.