0

I'm new to Node and I'm trying to download a file, hash it, then save it to disk using the hash as the file name. I'm getting correct hashes (I think) but the files are blank.

const fs = require("fs-extra")
const fetch = require("node-fetch")
const crypto = require('crypto')

const response = await fetch(url)
const sha256 = crypto.createHash("sha256")
sha256.setEncoding('hex')
response.body.pipe(sha256)
await new Promise(resolve => response.body.on("end", resolve))
sha256.end()
const hash = sha256.read()
const file = fs.createWriteStream(hash + ".jpg")
response.body.pipe(file)
Chris_F
  • 4,991
  • 5
  • 33
  • 63

1 Answers1

0

My trick for resolving your problem is storing your file with unique name (using current timestamp as name), and then you can hash stream (from response) and rename it.

I've tested this code and it's working well:

const fs = require("fs-extra")
const path = require('path');
const fetch = require("node-fetch")
const crypto = require('crypto')

const downloadImage = async (url) => {
  try {
    const response = await fetch(url);

    /** Store file with name current timestamp */
    const filename = "IMG_" + Date.now() + ".jpg";
    const dest = path.join(__dirname, filename);
    response.body.pipe(fs.createWriteStream(dest))

    /** Hash file */
    const sha256 = crypto.createHash("sha256")
    sha256.setEncoding('hex')
    response.body.pipe(sha256)
    await new Promise(resolve => response.body.on("end", resolve))
    sha256.end()
    const hash = sha256.read()

    /** Rename file with hash value */
    await fs.rename(dest, path.join(__dirname, hash + ".jpg"))

  } catch (err) {
    console.log(err);
  }
}

const url = "https://i0.wp.com/wptavern.com/wp-content/uploads/2016/07/stack-overflow.png?ssl=1";

downloadImage(url);

But you can create function for hashing stream (response you received) as utility, this is my recommend for your code:

const fs = require("fs-extra")
const path = require('path');
const fetch = require("node-fetch")
const crypto = require('crypto')

function streamHash(stream, algorithm = 'md5') {
  return new Promise((resolve, reject) => {
    let shasum = crypto.createHash(algorithm);
    try {
      stream.on('data', function (data) {
        shasum.update(data)
      })
      stream.on('end', function () {
        const hash = shasum.digest('hex')
        return resolve(hash);
      })
    } catch (error) {
      return reject(error);
    }
  });
}

const downloadImage = async (url) => {
  try {
    const response = await fetch(url);

    /** Store file with name current timestamp */
    const filename = "IMG_" + Date.now() + ".jpg";
    const dest = path.join(__dirname, filename);
    response.body.pipe(fs.createWriteStream(dest))

    /** Hash file */
    const hash = await streamHash(response.body, 'sha256');

    /** Rename file with hash value */
    await fs.rename(dest, path.join(__dirname, hash + ".jpg"))

  } catch (err) {
    console.log(err);
  }
}

const url = "https://i0.wp.com/wptavern.com/wp-content/uploads/2016/07/stack-overflow.png?ssl=1";

downloadImage(url);
Ha. Huynh
  • 1,772
  • 11
  • 27