为什么 fs.createReadStream ... pipeline(res) 锁定读取文件?

2024-02-13

我正在使用 Express 传输音频和视频文件根据这个答案 https://stackoverflow.com/a/24977085/304832。相关代码如下:

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> and <video>客户端上的元素。然而,在满足这些请求之后,另一个快速请求可以删除从文件系统流式传输的文件。第二个请求有点失败。

发生的情况是,只要文件至少被流式传输一次(意味着createReadStream在运行上面的代码时为文件路径调用),然后另一个不同的 Express 请求进入以删除该文件,该文件保留在文件系统上,直到 Express 停止。一旦express停止,这些文件就会从文件系统中删除。

这里究竟发生了什么?是吗fs or express那是锁定文件,为什么,以及如何让进程释放该文件以便可以删除它(在读取其内容并通过管道传送到响应之后,如果有待处理的内容)?

更新1:

我修改了上面的代码来设置autoClose: true对于第二个函数 arg,并添加了两个'end' and '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> or <audio>元素,仅'open'甚至被解雇。然后,当用户单击播放视频/音频时,会发出第二次请求,这第二次,两个请求'end' and 'close'事件触发,随后删除文件成功。

因此,当用户加载具有以下内容的页面时,该文件似乎被锁定<video> or <audio>获得它的元素source来自调用此函数的请求。直到播放该媒体文件后才会发出第二个请求,并且文件会被解锁。

我还发现关闭浏览器也会导致'end' and 'close'要触发的事件以及要解锁的文件。我猜我的快递做错了res使其无法正确关闭,但我仍然不确定那可能是什么。


事实证明,解决这个问题的方法是在每次请求期间从文件中读取并传输较小的数据块。在我的测试用例中,我正在流式传输 6MB MP4 视频文件。虽然我能够使用 Firefox 或 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,然后阻塞连接,直到用户操作导致它need文件的其余部分。这解释了为什么关闭浏览器或停止 Express 会导致文件被解锁,因为它关闭了来自浏览器或服务器端的连接。

我目前的解决方案是最多只发送 1MB(老派 1MB,1024 * 1024)一次块。相关代码可以在对OP中提到的问题的补充答案 https://stackoverflow.com/a/39056085/304832.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 fs.createReadStream ... pipeline(res) 锁定读取文件? 的相关文章

  • GET Ajax 在响应中返回 html 代码而不是 json 对象

    我有一个 ajax get 请求 如下所示 我正在使用 Nodejs Express 向 openshift 中的 server js 发出 GET 请求 但是 我在响应方法中获取 html 内容而不是 json 对象 这两个请求都是针对同
  • 如何使用 NodeJS 和 Express 为 OpenShift 应用程序配置路由

    我是 OpenShift 新手 我需要一些帮助来在 OpenShift 上配置我的应用程序的路由 这是我尝试部署的 NodeJS Express 应用程序中的端口和 IP 配置 const server port process env O
  • Node.js fast-csv 同步读取文件并返回数组

    我正在尝试读取 csv 文件并使用以下代码将其分配给数组 const fs require fs const csv require fast csv parse let data csv parseFile downloads aggio
  • 使用 puppeteer 配置 PDF 页面宽度

    我正在尝试使用 puppeteer 生成 pdf 但生成的 pdf 宽度很大 我想要一个 pdf 文件 它在一页中显示所有内容 并且宽度必须为 4 8 厘米 其中页面高度可以是其内容的任何长度 我在pdf中添加了配置 path filePa
  • TweetNaCl.js 最小公钥签名示例

    我试图了解如何基于位于的演示来实现一个最小的基本公钥签名示例here https tweetnacl js org sign 使用纯javascript 我的研究还没有产生一个简单的 javascript 示例 我可以用它来理解其内部工作原
  • Node.js 应用程序中的系统托盘图标

    这是我的 node js 应用程序中需要的 系统托盘图标 在应用程序工作期间更改此图标 单击图标后的菜单 创建带有登录 密码字段和确认按钮的窗口 这是我发现的 https github com appjs appjs https githu
  • Puppeteer 错误 错误:等待选择器超时

    目前我有一个网站 其 HTML 中有此内容 我通过检查chrome开发者工具中的元素确认了这一点 div class hdp photo carousel div class photo tile photo tile large 我直观地
  • 降低 Nodejs 服务器上的 CPU 利用率

    我正在研究降低 CPU 利用率的有趣方法 在 NodeJS 服务器上 在我的研究过程中 我发现了以下文章 http engineering linkedin com nodejs blazing fast nodejs 10 perform
  • 如何模拟 typeORM 的 getCustomRepository

    我想对一个在其构造函数中使用 getCustomRepository 的类进行单元测试 但我只是想不出一种简单的方法来模拟它 这是我的班级代码 import getCustomRepository from typeorm export c
  • 为什么名称为“下划线”或“lodash”?

    为什么这些库以 命名 其背后是否有某种意义或者原因是 只是因为我们可以 据我所知 下划线 and lodash做很多类似的事情 此外 这两个名字都指向 甚至它们的变量名也是 那么是否存在某种关系 这些库的工作 或者它只是一个名字 Lodas
  • 如何使用startsWith过滤并获取每个对象键的值?

    我试图通过获取每个键来过滤对象checkpoint并输出其值 目前 我只能输出键而不是值 下面 我有一个简单的对象 我正在使用过滤器和startsWith 我怎样才能得到这些值呢 var data practicals 0 checkpoi
  • 有没有办法防止 neDB 集合数组中的条目重复?

    var addNewUser function id chatId db update id id push users chatId function err numAffected code after the record is up
  • Node/Express 4.0 中可以声明全局变量吗

    我有多个需要访问数据库的路线 对于开发我使用本地数据库 显然生产我使用托管数据库 唯一的问题是每次我去推送版本时我都必须手动更改数据库链接 e g var mongodb require mongojs connect urlhere Co
  • 使用express/connect-redis在页面重新加载时抓取现有会话

    使用 connect express 和 socket io 我试图让我的应用程序在重新连接时获取会话详细信息 我的会话显然在客户端连接时工作 但如果我刷新浏览器上的页面 它会忘记所有内容 我的会话cookie肯定是一样的 所以不是那样的
  • 如何在 Mongoose 中定义排序函数

    我正在开发一个小型 NodeJS Web 应用程序 使用 Mongoose 访问我的 MongoDB 数据库 我的收藏的简化架构如下 var MySchema mongoose Schema content type String loca
  • Node.js - 将数据缓冲到 Ffmpeg

    我使用 Node js 和 Ffmpeg 来创建动画 因为我试图避免第三方 avi mp4 解析器 所以我决定将动画输出为原始 rgb24 数据文件 然后使用一些程序将其转换为 mp4 文件 我发现 Ffmpeg 是免费且开源的 它完全可以
  • 将 Node.js 升级到最新版本

    所以 我安装了 Node js 现在当我尝试安装 Mongoosejs 时 我收到一条错误 告诉我没有所需的 Node js 版本 我有 v0 4 11 需要 v0 4 12 我怎样才能升级到这个版本 我想我只能使用最新版本再次安装它 但在
  • C# 锁(mylocker) 不起作用

    我有很多 Web 服务调用 异步 在回调中 我会将结果绘制到 Excel 中 我想同步绘图方法 所以我使用以下内容 但是 从我在 Visual Studio 中追踪到 每次 lock locker 都会成功 并且有许多线程运行clearco
  • AWS DynamoDb DocumentClient - 从项目数组创建批量写入 - node.js

    我正在尝试执行batchWrite使用 DynamoDB 的操作DocumentClient来自项目数组 JSON 这是我的代码 var items for i 0 i lt orders length i var ord orders i
  • Webworker-threads:在工作线程中使用“require”可以吗?

    使用 Sails js 我正在测试 webworker threads https www npmjs com package webworker threads https www npmjs com package webworker

随机推荐

  • 我们如何在 Comparator.comparing 中传递变量字段/方法名称

    我有一个Report String name Date date int score 班级 我希望能够使用新的 java 8 语法对任何成员变量的报告列表进行排序 所以java 8提供了这个新的 list sort Comparator c
  • Android studio 虚拟设备未加载

    我有 4GB 内存 android studio 虚拟设备显示 ANDROID 所以加载是无限的 它没有结束 我已经等太久了 可能是什么问题 无论我使用什么应用程序 您尝试过使用 Genymotion 吗 它比普通虚拟设备好数百倍 这里有一
  • Ruby - 将目录添加到 $LOAD_PATH - 它有什么作用?

    这实际上是关于这个问题的一个问题 将目录添加到 LOAD PATH Ruby https stackoverflow com questions 837123 adding a directory to load path ruby 将目录
  • 使用 gulp 创建 tar 档案

    我正在使用 gulp tar 创建一个 tar 文件 如何添加顶级文件夹 以便当用户运行时tar xzf myArchive tar它解压到特定的文件夹中 这是我的代码 gulp task prod min gittag function
  • div 向下滑动时自动聚焦在输入字段上

    我有一个隐藏的div 单击按钮时 div 会向下滑动并带有输入字段 如何让这个输入框在 div 向下滑动时自动对焦 谢谢
  • sphinx autodoc包含子功能

    我想在 sphinx 文档中自动包含函数的子函数 有什么选择呢 我的代码看起来像 import numpy def mainfunc to be documented def subfunc to be documented as well
  • PCRE pcre_exec 线程安全吗?

    我有一个 C 程序 它使用 PCRE 正则表达式来确定 cgroup 中的进程是否应添加到一个变量或另一个变量 我生成一个线程来读取每个正在运行的 cgroup 中的 cpuacct stat 文件 其中线程数从未超过核心数 然后将这些样本
  • Haskell 中的 S 组合器

    可以模拟一下S组合器 https en wikipedia org wiki SKI combinator calculus仅使用标准函数 不通过方程定义 并且不使用 lambda 匿名函数 在 Haskell 中表达 我希望它能按类型 a
  • Facebook“点赞”推荐点击添加变量;无法识别链接的页面作为喜欢的页面

    所以我有一个网站 我们称之为foo com并且所有页面都有点赞按钮插件 https developers facebook com docs reference plugins like 在上面 每个页面上都重新散列相同的代码 所以我 喜欢
  • 如何在 Vue 中条件绑定 v-model?

    在 JavaScript 中 对象可以选择扩展值 如下所示 const payload name Joseph isMember credential true 在 React 中 JSX 可以像这样可选地传递 props
  • 如何使用 SetConsoleHandler() 阻止退出调用

    我知道我必须使用SetConsoleCtrlHandler 如果我想管理控制台关闭事件 不知道怎么屏蔽CTRL CLOSE EVENT 我尝试过如果捕获该事件则返回 false true 但没有成功 这是我到目前为止所得到的 谢谢 Anto
  • 设置运行/段落样式以支持 RTL 和 LTR 单词

    我怎样才能设计一个Run and or Paragraph支持 RTL 和 LTR 字 问题是 我有一个复杂的文本 其中包含波斯语和英语单词 我正在尝试创建一个 docx使用 OpenXML SDK 的文档 但是 英语单词也可以得到 RTL
  • 对 PowerPC 寄存器值感到困惑)?

    所以 我一直在学习 PowerPC 来完成 Xbox 的简单逆向项目 但我总是对这样的事情感到困惑 lwz r11 0 r29 Loads 0x34 from 0x10710 and stores in r11 lwz r10 4 r29
  • android:如何使用属性集构造函数实例化我的自定义视图

    我的自定义视图具有动态自定义属性 例如背景图像属性 通过当前星期分配 我不想使用构造函数 CalendarView Context context AttributeSet attrs 来传递多个属性 并且我尝试使用 Xml asAttri
  • Tomcat 7 作为 Windows 服务无法从其他系统访问

    我已经下载了适用于 32 位 Windows 7 机器的 Tomcat 7 zip 我已经解压了该包并使用 bin service bat 创建了 Windows 服务 但是当我从 windows services msc 启动服务时 我无
  • 在远程 ssh 命令中传递变量

    我希望能够使用 ssh 从我的机器运行命令并传递环境变量 BUILD NUMBER 这就是我正在尝试的 ssh email protected cdn cgi l email protection tools myScript pl BUI
  • 为树状图中的刻度标签着色以匹配簇颜色

    如何为树状图的标签单独着色 使其与 MATLAB 中簇的颜色相匹配 这是使用下面我的答案中的代码生成的所需输出示例 请注意 标签只是 50 个字符系列 A r 如果有更直接的方法来做到这一点 请发布答案 因为我无法通过谷歌搜索找到解决方案
  • 两个节点之间的设备树依赖关系

    我有两个设备树节点 一个设置 GPIO 引脚 另一个配置一个 i2c 总线 例如 gpio2 en gpio gpio hog gpios lt 5 0 gt output high i2c1 gpiom1 gpio 27 compatib
  • SQL Server:搜索所有表中的特定 GUID

    我发现需要清理一些数据 并且我需要找到一些特定的指南 即唯一标识符 在 SQL Server 我想出了一个存储过程SELECT从当前数据库中每个表的每个 uniqueidentifier 列中查找 如果找到 guid 则返回一个结果集 它使
  • 为什么 fs.createReadStream ... pipeline(res) 锁定读取文件?

    我正在使用 Express 传输音频和视频文件根据这个答案 https stackoverflow com a 24977085 304832 相关代码如下 function streamMedia filePath req res cod