我目前正在为我的大学项目开发视频流服务器,并且使用 MongoDB GridFS 以及官方 MongoDB Node.js 驱动程序。在我的项目中,我尝试下载存储在 GridFS 中的视频文件的特定部分作为块。不幸的是,我在这个过程中遇到了“FileNotFound”错误
app.get('/download-video', async (req, res) => {
if (db === null) {
console.error('Error connecting to MongoDB:',);
res.status(500).send('Error connecting to MongoDB');
return;
}
const chunkSizeBytes = 50 * 1024; // 50kb chunk size as an example
// Create a GridFSBucket with the desired chunk size
const bucket = new mongodb.GridFSBucket(db, { chunkSizeBytes });
// Specify the file ID you want to retrieve
const fileId = '514a65328a1e0fef0c936c1109bbc946.mp4';
// Get the file information
const fileInfo = await db.collection('fs.files').findOne({ filename: fileId });
if (!fileInfo) {
console.error('File not found');
res.status(400).json({ message: "file not found" })
return;
}
// Calculate the total number of chunks based on the file size and chunk size
const totalChunks = Math.ceil(fileInfo.length / chunkSizeBytes);
// Array to store downloaded chunks
const chunksArray = [];
try {
// Download each chunk one by one
for (let i = 0; i < totalChunks; i++) {
const downloadStream = bucket.openDownloadStream(fileId, { start: i * chunkSizeBytes });
let chunkData = Buffer.from([]);
downloadStream.on('data', (chunk) => {
// Append the chunk to the existing data buffer
chunkData = Buffer.concat([chunkData, chunk]);
});
downloadStream.on('end', () => {
// Process the downloaded chunk, e.g., save to a file, send to the client, etc.
console.log(`Downloaded chunk ${i + 1} of ${totalChunks}`);
// Add the chunk to the array
chunksArray.push(chunkData);
// If this is the last chunk, concatenate and process the complete video
if (i === totalChunks - 1) {
// Concatenate all chunks into a single Buffer
const completeVideo = Buffer.concat(chunksArray);
// Specify the path where you want to save the complete video
const outputPath = 'path/to/output/video.mp4';
// Save the complete video to a file
fs.writeFileSync(outputPath, completeVideo);
console.log('Video saved:', outputPath);
}
});
downloadStream.on('error', (error) => {
console.error(`Error downloading chunk ${i + 1}:`, error);
// res.send(400).json({message:"oops error"});
return;
});
}
} catch (error) {
console.log(error.message);
res.json({ message: error.message });
//Error downloading chunk 102: Error: FileNotFound: file 514a65328a1e0fef0c936c1109bbc946.mp4 was not found
}
});
我正在寻求帮助来理解和解决此问题。任何指导或见解将不胜感激。
我不使用 MongoDB,但根据一般编码经验,以下是我认为您显示的代码中存在错误的内容:
(1) 使用实际(十进制)字节长度来获取所需的字节数
尝试更换:
const chunkSizeBytes = 50 * 1024; // 50kb of chunk size as an example
有了这个新的计算版本:
const chunkSizeBytes = 50 * 1000; // 50 000 bytes of chunk size as an example
不用担心文件存储技术问题,例如
1 KiloByte == 1024 bytes
等。(2) 仔细检查您的阅读位置。
您的代码 (示例,其中
i
是 101):
const downloadStream = bucket.openDownloadStream(fileId, { start: i * chunkSizeBytes });
使用计算器检查您的
101 * chunkSizeBytes
是否在文件的字节长度内。
还可以尝试在给定配置对象中设置
end
位置以及 start
位置。
例如:
{ start: (i * chunkSizeBytes), end: ((i * chunkSizeBytes) + chunkSizeBytes) }
注意: 您的最后一个块可以设置较小的大小,以便获得上次读取中未形成完整块的剩余最后几个字节。
如果没有
end
,您可能正在下载整个文件的字节(从开始位置到文件结尾),只是在从下一个块的位置读取时覆盖相同的数据(也读取到文件末尾),然后重复如此步骤,直到稍后出现错误为止。
(3) 文件保存后应返回。
在您的
if (i === totalChunks - 1)
块中,您应该使用 return;
退出该函数。
console.log('Video saved:', outputPath);
return;
这将保证退出并停止任何进一步尝试读取下载文件的操作。