首页 > 解决方案 > NodeJS - 从流与本地文件生成哈希时的不同结果

问题描述

似乎如果我散列一个文件流,我得到的散列与我将流写入磁盘、读回然后散列它不同。可能是编码问题,或者我错了哈希应该相同?

这是我的测试用例

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

标签: javascriptnode.js

解决方案


那是你的错误。根据节点 js 文件:

调用 stream.end() 方法后会发出“完成”事件,并且所有数据都已刷新到底层系统。

当函数中发出完成事件时,writeFile流完成写入数据,hashFileStream函数没有任何剩余。

如果您只想检查哈希字符串,最简单的方法是分离代码并看到它们是相同的:

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

推荐阅读