【发布时间】:2016-12-27 06:08:33
【问题描述】:
我正在使用 express 流式传输音频和视频文件 according to this answer。相关代码如下:
function streamMedia(filePath, req, res) {
// code here to determine which bytes to send, compute response headers, etc.
res.writeHead(status, headers);
var stream = fs.createReadStream(filePath, { start, end })
.on('open', function() {
stream.pipe(res);
})
.on('error', function(err) {
res.end(err);
})
;
}
这可以很好地将字节流式传输到客户端上的<audio> 和<video> 元素。但是,在处理完这些请求后,另一个快速请求可以从文件系统中删除正在流式传输的文件。第二个请求失败了。
只要文件至少流式传输一次(意味着在运行上面的代码时为文件的路径调用了createReadStream),就会出现不同的快速请求来删除文件,文件保留在文件系统上,直到 express 停止。一旦 express 停止,文件就会从文件系统中删除。
这里到底发生了什么?是fs 还是express 锁定了文件,为什么,以及如何让进程释放文件以便可以删除它(在其内容被读取并通过管道传输到响应之后,如果有的话待定)?
更新 1:
我修改了上面的代码,为第二个函数 arg 设置了 autoClose: true,并添加了 'end' 和 'close' 事件处理程序,如下所示:
res.writeHead(status, headers);
var streamReadOpts = { start: start, end: end, autoClose: true };
var stream = fs.createReadStream(filePath, streamReadOpts)
// previous 'open' & 'error' event handlers are still here
.on('end', function () {
console.log('stream end');
})
.on('close', function () {
console.log('stream close');
})
我发现,当页面最初加载 <video> 或 <audio> 元素时,甚至只会触发 'open'。然后当用户点击播放视频/音频时,会发出第二次请求,这第二次,'end' 和 'close' 事件都会触发,随后删除文件成功。
因此,当用户加载具有<video> 或<audio> 元素的页面时,文件似乎被锁定,该元素从调用此函数的请求中获取其source。直到播放该媒体文件后,才会发出第二个请求,并且文件被解锁。
我还发现关闭浏览器也会导致'end' 和'close' 事件触发,并且文件被解锁。我的猜测是我对快递 res 做错了什么,使其无法正常关闭,但我仍然不确定那可能是什么。
【问题讨论】:
标签: node.js express locking video-streaming fs