It seems like if I hash a file stream I get a different hash than if I write the stream to disk, read it back and then hash it. Possibly an encoding issue or I'm wrong that the hashes SHOULD be the same?
Here's my test case
const fs = require("fs");
const crypto = require("crypto");
const https = require("https");
(async ()=>{
const testUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/SIPI_Jelly_Beans_4.1.07.tiff/lossy-page1-256px-SIPI_Jelly_Beans_4.1.07.tiff.jpg"
const filePath = "./testFile.jpg";
https.get(testUrl, async function(response) {
await writeFile(filePath, response);
const streamHash = await hashFileStream(response)
const fileHash = await hashLocalFile(filePath)
console.log("Stream Hash", streamHash);
console.log("File hash", fileHash);
});
})()
async function writeFile(filePath, stream) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(filePath);
stream.pipe(file)
.on('finish', () => {
resolve(filePath);
})
.on('error', (error)=>{
console.error(error);
reject(error);
})
})
}
async function hashFileStream(stream){
return new Promise((resolve, reject)=>{
const hash = crypto.createHash('md5').setEncoding('hex');
stream.pipe(hash)
.on('finish', ()=>{
resolve(hash.read())
})
.on('error', (error)=>{
reject(error)
})
})
}
async function hashLocalFile(filepath){
const readStream = fs.createReadStream(filepath);
return hashFileStream(readStream);
}
That is your mistake. According to node js documents :
The 'finish' event is emitted after the stream.end() method has been called, and all data has been flushed to the underlying system.
When finish event emitted in writeFile function then stream is done writing data and nothing remains for hashFileStream function.
If you want to just check hash strings, the easiest way is to separate the code and will see they are same:
const fs = require("fs");
const crypto = require("crypto");
const https = require("https");
(async ()=>{
const filePath = "./testFile.jpg";
const testUrl = "https://static2.farakav.com/files/pictures/watermark/01661368.jpg"
https.get(testUrl, async function(response) {
await writeFile(filePath, response);
const fileHash = await hashLocalFile(filePath)
console.log("File hash", fileHash);
});
https.get(testUrl, async function(response) {
const streamHash = await hashFileStream(response)
console.log("Stream Hash", streamHash);
});
})()
async function writeFile(filePath, stream) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(filePath);
stream.pipe(file)
.on('finish', () => {
resolve(filePath);
})
.on('error', (error)=>{
console.error(error);
reject(error);
})
})
}
async function hashFileStream(stream){
return new Promise((resolve, reject)=>{
const hash = crypto.createHash('md5').setEncoding('hex');
stream.pipe(hash)
.on('finish', ()=>{
hash.end();
resolve(hash.read())
})
.on('error', (error)=>{
reject(error)
})
})
}
async function hashLocalFile(filepath){
const readStream = fs.createReadStream(filepath);
return hashFileStream(readStream);
}