node.js - 管道失败后无法发送数据响应
问题描述
我正在尝试从 mysql 查询一些数据,将其转换为 csv,然后最终将其下载为 csv。目标是使用流来实现这一点。
res.set('Content-Type', 'text/csv')
res.set('Content-Disposition', `attachment; filename="${req.query?.filename || 'export'}.csv"`)
const sqlStream = connection.query('SELECT * FROM whatever_table').stream({highWaterMark: 5}) // --> using mysql2 adapter
const formatCsvStream = formatCsv({delimiter: ';'}) // --> using @fast-csv/format
try {
// using {pipeline} from require('stream/promises')
await pipeline(
sqlStream,
formatCsvStream,
res // --> express response
)
} catch (err) {
console.error(err)
return res.status(500).json({message: 'Please check the application logs for more details.'}).end()
}
如果在响应之前没有错误,一切都会按预期工作。但是如果确实发生了错误(例如,我们从表中选择了数据库中不存在的数据),浏览器将使用 ERR_EMPTY_RESPONSE 进行响应,而不是发送在 catch 块中定义的 json 错误消息。
如果我从管道中删除res,浏览器将显示正确的响应(显然在这种情况下下载将不起作用)。
我尝试在返回 .json 之前删除 Content-Type 和 Content-Disposition 标头。我还尝试了常规的 .pipe() 语法,但没有任何运气。
管道失败后如何继续使用快速响应对象?任何建议都会很棒!
解决方案
到达catch
块时,对象的套接字res
已经被管道销毁。如果源中或中间转换发生错误,管道会“转发错误”并破坏目标。
尝试以下操作:
sqlStream.on("error", function(err) {
console.error(err);
if (!res.headersSent)
res.status(500).json({message: 'Please check the application logs for more details.'}).end();
});
try {
await pipeline(sqlStream, formatCsvStream, res);
} catch (err) {} // to avoid unhandled promise rejections. No further output here.
推荐阅读
- c# - 使用 MVC 的实体框架代码优先:添加过滤功能 (OrderBy) 会破坏 ViewBag 上下文
- python - Python:在'_init_.pyi |_init_.pyi 中找不到引用'uic'
- excel - 查找最新文件并复制到另一个工作簿
- javascript - 如何在 javaScript 中编写我的 onclick 函数并将其绑定到 innerHTML
- asp.net - 无法解决“配置不存在...”错误
- python - 使用 Pandas 绘制树状可视化
- express - 如何将响应标头添加到 NextJS 公共资产?
- discord.js - 遇到问题 - 命令处理程序
- javascript - 在 Javascript 中访问(嵌套)对象和数组
- php - 如何在 Laravel 中将 pdf 附加到邮件中