如何以快递方式流式传输响应?
Posted
技术标签:
【中文标题】如何以快递方式流式传输响应?【英文标题】:How do I stream response in express? 【发布时间】:2016-12-11 20:08:05 【问题描述】:我一直在尝试让一个快速应用程序以流的形式发送响应。
var Readable = require('stream').Readable;
var rs = Readable();
app.get('/report', function(req,res)
res.statusCode = 200;
res.setHeader('Content-type', 'application/csv');
res.setHeader('Access-Control-Allow-Origin', '*');
// Header to force download
res.setHeader('Content-disposition', 'attachment; filename=Report.csv');
rs.pipe(res);
rs.push("USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD\n");
for (var i = 0; i < 10; i++)
rs.push("23,John Doe,1234,500,SUBSCRIPITON,100,ACTIVE,30\n");
rs.push(null);
);
当我将“rs.pipe(res)”替换为“rs.pipe(process.stdout)”时,它会在控制台中打印。但是如何让它在快递应用中运行呢?
Error: not implemented
at Readable._read (_stream_readable.js:465:22)
at Readable.read (_stream_readable.js:341:10)
at Readable.on (_stream_readable.js:720:14)
at Readable.pipe (_stream_readable.js:575:10)
at line "rs.pipe(res);"
【问题讨论】:
你需要继承Readable
,它需要有一个_read
方法。但为什么不直接使用res.write(...)
?
我将如何在这里使用 res.write()?
【参考方案1】:
您不需要可读的流实例,只需使用res.write()
:
res.write("USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD\n");
for (var i = 0; i < 10; i++)
res.write("23,John Doe,1234,500,SUBSCRIPITON,100,ACTIVE,30\n");
res.end();
这是因为在 Express 中,res
是基于 Node 自己的 http.serverResponse
,所以它继承了它的所有方法(如 write
)。
【讨论】:
如果我在响应中添加数千行,这仍然不是问题吗? 不,因为res
也是一个流。
谢谢。我整天都在尝试使用可读流来做到这一点。
这不会流式传输,缓冲直到 res.end() 被调用
@chetandev 您的浏览器/客户端可能会缓冲它,但 Express 或 http
不会。您可以使用像nc/netcat
这样的非缓冲 TCP 客户端对此进行测试。见this gist。【参考方案2】:
我能够让它工作。
将此代码放入您的 Express 路由器中。 打开网络浏览器 转到http://yourdomain/yourrouterpath/stream...
router.get('/stream', function (req, res, next)
//when using text/plain it did not stream
//without charset=utf-8, it only worked in Chrome, not Firefox
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader('Transfer-Encoding', 'chunked');
res.write("Thinking...");
sendAndSleep(res, 1);
);
var sendAndSleep = function (response, counter)
if (counter > 10)
response.end();
else
response.write(" ;i=" + counter);
counter++;
setTimeout(function ()
sendAndSleep(response, counter);
, 1000)
;
;
【讨论】:
【参考方案3】:为了使用 tar-stream,我需要以 express 流式传输响应。以下是我的做法,以防它对任何人有所帮助。
请求来自存储在服务器上的 tar 文件中的单个文件。
const fs = require("fs"),
tar = require("tar-stream");
app.get("/fileFromTar/*", (req, res) =>
const fileWanted = req.params[0],
readStream = fs.createReadStream('myTarFile.tar'),
extractor = tar.extract();
extractor.on('entry', (header, stream, next) =>
stream.on('end', next);
if (header.name === fileWanted)
const size = header;
res.set(
"Content-Type": 'audio/flac', // or whichever one applies
"Content-Length": size,
"Content-Range": `bytes 0-$size/$size`
);
stream.pipe(res);
else stream.resume();
);
readStream.pipe(extractor);
);
【讨论】:
以上是关于如何以快递方式流式传输响应?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式使用 AWS Media Convert 流式传输视频