我目前正在管理的后端存在一些问题。它使用GridFS在MongoDB中存储和检索视频。现在已经工作了半年左右,但是突然之间不再可用了。到目前为止,这是代码
const getByFilename = async (req: Request, res: Response, next: NextFunction) => {
try {
let filename = req.params.Filename
let media = await MediaService.getByFilename(filename);
if (req.headers.range) {
let parts = req.headers.range.replace(/bytes=/, '').split('-');
let partialStart = parts[0];
let partialEnd = parts[1];
let start = parseInt(partialStart, 10);
let end = partialEnd ? parseInt(partialEnd, 10) : media.length - 1;
let chunkSize = (end - start) + 1;
res.writeHead(206, {
'Accept-Ranges': 'bytes',
'Content-Length': chunkSize,
'Content-Range': `bytes ${start}-${end}/${media.length}`,
'Content-Type': media.contentType,
});
let readstream: ReadStream = grid.gfs.createReadStream({
filename,
range: {
startPos: start,
endPos: end
}
}).pipe(res);
readstream.on('data', buff => {
start += buff.length;
if (start >= end) {
return res.end();
} else {
res.write(buff);
}
});
readstream.on('err', err => {
handleError(err, res);
});
readstream.pipe(res);
} else {
res.header('Content-Length', media.length);
res.header('Content-Type', media.contentType);
res.header('Content-Metadata', JSON.stringify(media.metadata))
grid.gfs.createReadStream({
filename
}).pipe(res);
}
} catch (err) {
handleError(err, res);
}
}
现在,我遇到的第一个错误是HTTP标头在发送后尝试设置。这似乎是很明显的(至少我猜是这样),因为代码首先通过直接管道设置变量readstream,然后在try块的末尾再次通过管道传送readstream。尽管这似乎很明显,但我无法确定过去的工作方式(仍然在我的产品的Docker容器中工作)。 gridfs-stream也于4年前发布,因此版本更改也不是问题的原因。
现在,如果我修改代码,则首先创建readstream(无需直接管道传递)
let readstream: ReadStream = grid.gfs.createReadStream({
filename,
range: {
startPos: start,
endPos: end
}
});
然后像读取流的管道之前和之后一样进行事件处理
readstream.pipe(res)
这更有意义,似乎浏览器将只接收视频的第一部分。
有什么想法吗?我有点迷路了
据我了解,这是应该如何工作的
但是在调试时,我注意到以下行为。