我正在根据这个答案使用express流音频和视频文件。相关代码如下:
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
在运行上面的代码时调用了a的文件路径),然后出现另一个不同的express请求删除该文件,该文件将保留在文件系统上直到express已停止。一旦Express停止,文件将从文件系统中删除。
这到底是怎么回事?是它fs
还是express
那个正在锁定文件,为什么?我如何获得释放文件的过程,以便可以将其删除(在读取其内容并将其通过管道传输到响应后,如果有任何未决的内容)?
我已经修改了上面的代码autoClose: true
以为第二个函数arg设置,并添加了'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
以使其无法正确关闭,但是我仍然不确定那会是什么。
事实证明,解决方案是在每个请求期间从文件中读取并传送较小的数据块。在我的测试用例中,我正在流式传输一个6MB的MP4视频文件。尽管我可以使用Firefox或chrome重现该问题,但我使用chrome进行了调试,发现客户端阻止了该流。
最初加载页面时,会出现一个类似于以下内容的元素:
<video> <!-- or <audio> -->
<source src="/path/to/express/request" type="video/mpeg" /> <!-- or audio/mpeg -->
</video> <!-- or </audio> -->
正如在OP中引用的其他答案中所记录的那样,chrome将发送带有范围标头的请求,如下所示:
Range:bytes=0-
对于此请求,我的函数正在发送整个文件,我的响应如下所示:
Accept-Ranges:bytes
Connection:keep-alive
Content-Length:6070289
Content-Range:bytes 0-6070288/6070289
Content-Type:video/mp4
但是,chrome并没有读取全部内容。它仅读取前3-4MB,然后阻止连接,直到用户操作导致它需要其余文件为止。这解释了为什么关闭浏览器或停止express导致文件被解锁的原因,因为它关闭了来自浏览器或服务器端的连接。
我当前的解决方案是一次最多只能发送1MB(旧学校为1MB 1024 * 1024
)块。相关的代码可以在OP中引用的问题的其他答案中找到。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句