使用 Fetch API 和 fs.createWriteStream 对文件进行流式响应
Posted
技术标签:
【中文标题】使用 Fetch API 和 fs.createWriteStream 对文件进行流式响应【英文标题】:Stream response to file using Fetch API and fs.createWriteStream 【发布时间】:2017-11-24 04:06:52 【问题描述】:我正在创建一个 Electron 应用程序,我想将图像流式传输到文件中(所以基本上下载它)。
我想使用本机 Fetch API,因为请求模块的开销很大。
但是响应上没有管道方法,所以我不能做类似的事情
fetch('https://imageurl.jpg')
.then(response => response.pipe(fs.createWriteStream('image.jpg')));
那么我该如何组合fetch
和fs.createWriteStream
?
【问题讨论】:
【参考方案1】:Fetch 并不能真正使用开箱即用的 nodejs Streams,因为浏览器中的 Stream API 与 nodejs 提供的不同,即您不能将浏览器流通过管道传输到 nodejs 流中,反之亦然。
electron-fetch 模块似乎可以为您解决这个问题。或者你可以看看这个答案:https://***.com/a/32545850/2016129 有一种下载文件的方法,而不需要 nodeIntegration。
还有needle,一个更小的替代大请求,当然支持流。
【讨论】:
这不是真的。看看这里developer.mozilla.org/en-US/docs/Web/API/Streams_API/… 虽然浏览器支持流,但它们与 nodejs 的流并不真正兼容。您必须使用某种中间件来连接两者。【参考方案2】:我让它工作了。我做了一个函数,将响应转换为可读流。
const responseToReadable = response =>
const reader = response.body.getReader();
const rs = new Readable();
rs._read = async () =>
const result = await reader.read();
if(!result.done)
rs.push(Buffer.from(result.value));
else
rs.push(null);
return;
;
return rs;
;
有了它,我可以做到
fetch('https://imageurl.jpg')
.then(response => responseToReadable(response).pipe(fs.createWriteStream('image.jpg')));
【讨论】:
小心!这会将文件的全部内容加载到内存中...下载 2 GB 文档时可能不理想...您可能会耗尽内存。 @KarstenDaemen 你能指出哪一行代码将它全部加载到内存中吗?我认为const result = await reader.read()
这行只读取了一个块。以上是关于使用 Fetch API 和 fs.createWriteStream 对文件进行流式响应的主要内容,如果未能解决你的问题,请参考以下文章
使用 ReactJS 和 fetch-api 访问和显示 JSON 时遇到问题
Morgan Logger + Express.js:写入文件并在控制台中显示