上载然后将文件下载到 MongoDB GridFS 时哈希不匹配

问题描述

我有一个用例:

在第一个服务中:我正在使用 GridFS 上传文件并将它们存储在 MongoDB 上,然后公开REST 端点下载文件

// Controller
@Get(':md5')
async getFile(@Param('md5') md5: string,@Res() res) {        
  // const file = await this.fileService.findInfo(md5)
  const filestream = await this.fileService.readStream(md5)
  if(!filestream){
      throw new HttpException('An error occurred while retrieving file',HttpStatus.EXPECTATION_Failed)
  }
  res.header('Content-Type','application/octet-stream');
  return filestream.pipe(res)
}

// Service
async readStream(md5: string): Promise<GridFSBucketReadStream> {
  const fileMetadata = await this.getobjectIdFromMd5(md5);
  const id = fileMetadata.id;
  const db = await this.getDatabase();
  const fileModel = new MongoGridFS(db,'fs');
  return await fileModel.readFileStream(id);
}

public async getobjectIdFromMd5(md5: string): Promise<{ id: string,fileName: string }> {
  const db = await this.getDatabase();
  const document = await db.collection('fs.files').findOne({ 'md5': md5 });
  if (document === null) {
    return null;
  }
  return { id: document._id,fileName: document.filename };
}
private async getBucket() {
  const db = await this.getDatabase();
  var bucket = new GridFSBucket(db);
  return bucket;
}

private async getDatabase() {
  const client: MongoClient = await MongoClient.connect(this.uri,{ useUnifiedTopology: true });
  const db = client.db(this.dbname);
  return db;
}

在第二个服务中:我使用以下代码下载文件计算文件的哈希以确保文件未被篡改。 >

public async downloadFile(fileNAme,filehash) {
  const file: string = `./temp-files/${fileName}`;
  axios({
      method: 'get',url: `http://localhost:8000/api/download/${filehash}`,responseType: 'stream',}).then((response) => {
      response.data.pipe(fs.createWriteStream(file));
      this.matchHashes(file,filehash);
  });
}

private matchHashes(filePath: string,serverHash: string) {
  const crypto = require('crypto');
  const fileData = fs.readFileSync(filePath);
  const computedHash = crypto.createHash('md5').update(fileData).digest('hex');

  console.log('Server Hash: ' + serverHash);
  console.log('Hash after download from mongo: ' + computedHash)

  if (computedHash !== serverHash) {
      throw new Error('files hash mismatch');
  }
}

问题:我将计算出的 md5 与 MongoDB GridFS md5 哈希生成的 md5 匹配,有时某些文件的哈希匹配某些文件的某些文件此匹配失败,行为是随机的。 我什至尝试在上传文件之前以及执行 GET 操作和从 mongo 获取文件之后计算 sha256 而不是 md5,看到了相同的行为。

控制台日志:

Server Hash: d28e404f87957bfdc7548b579f14c082
Hash after download from mongo: d41d8cd98f00b204e9800998ecf8427e
(node:6615) UnhandledPromiseRejectionWarning: Error: files hash mismatch
...

当我尝试使用 MongoDB 内置驱动程序计算 md5 哈希值时,为其提供存储文件的 ObjectId:

db.adminCommand({ filemd5: ObjectId("60cca45292a3424b34f02b55"),root: "fs" })

它返回:

{
    "numChunks" : 0,"md5" : "d41d8cd98f00b204e9800998ecf8427e","ok" : 1.0
}

这相当于使用 GET REST 调用下载文件后计算出的哈希值。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)