Несоответствие хэша при загрузке и последующей загрузке файла в MongoDB GridFS

#node.js #mongodb #gridfs #gridfs-stream

Вопрос:

У меня есть пример использования, когда:

В первой службе: я загружаю файлы и сохраняю их в MongoDB с помощью GridFS, а затем предоставляю конечные точки 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 с md5, сгенерированным хэшем md5 MongoDB GridFS.Иногда хэш совпадает для некоторых файлов, для некоторых файлов это совпадение не удается. Поведение является случайным.
Я даже попытался вычислить sha256 вместо md5 как до загрузки файла, так и после выполнения операции GET и извлечения файла из mongo, наблюдается то же поведение.

Console log:

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

And when I try to compute the md5 hash using MongoDB inbuild driver providing it the ObjectId of the stored file:

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

it returns:

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

что эквивалентно вычисленному хэшу после загрузки файла с помощью вызова GET REST.