#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.