我正在尝试使用 StreamSaver.js 将大型数据文件从服务器直接下载到文件系统在 Angular 组件中。但是在 ~2GB 之后会发生错误。似乎数据首先流式传输到浏览器内存中的 blob 中。并且可能存在 2GB 的限制。我的代码基本上取自 StreamSaver 示例。知道我做错了什么以及为什么文件没有直接保存在文件系统上吗?
服务:
public transferData(url: string): Observable<Blob> {
return this.http.get(url, { responseType: 'blob' });
}
组件:
download(url: string) {
this.extractionService.transferData(url)
.subscribe(blob => {
const fileStream = streamSaver.createWriteStream('data.tel', {
size: blob.size
});
const readableStream = blob.stream();
if (window.WritableStream && readableStream.pipeTo) {
return readableStream
.pipeTo(fileStream)
.then(() => console.log("done writing"));
}
const writer = fileStream.getWriter();
const reader = readableStream.getReader();
const pump = () =>
reader.read()
.then(res => res.done ? writer.close() : writer.write(res.value).then(pump));
pump();
});
}
请求文件的头部:
“内容类型:应用程序/八位字节流\r\n”
"Content-Disposition: attachment; filename=data.tel\r\n"
最佳答案
建议/背景
StreamSaver 适用于那些在客户端生成大量数据的用户,例如长时间的摄像机记录。如果文件来自云并且您已经拥有 Content-Disposition
附件 header ,那么您唯一需要做的就是在浏览器中打开此 URL。
有几种方法可以下载文件:
-
location.href = url
-
<a href="url">download</a>
-
<iframe src="url" hidden>
- 对于那些需要发布数据或使用其他 HTTP 方法的人,他们可以发布一个(隐藏的)
<form>
相反。
只要浏览器不知道如何处理该文件,它就会触发下载,这就是您已经在使用 Content-Type: application/octet-stream
所做的事情。
由于您使用 Ajax 下载文件并且浏览器知道如何处理数据(将其提供给主 JS 线程),那么 Content-Type
和 Content-Disposition
没有任何目的。
StreamSaver 试图模仿服务器如何使用 ServiceWorkers 和自定义响应来保存文件。
您已经在服务器上这样做了!您唯一需要做的就是停止使用 AJAX 下载文件。所以我认为您根本不需要 StreamSaver。
你的问题
... 是先将整个数据作为 Blob 下载到内存中,然后再保存文件。这违背了使用 StreamSaver 的全部目的,那么您也可以使用更简单的 FileSaver.js 库,或者像 FileSaver.js 那样从 Blob 手动创建对象 url + 链接。
Object.assign(
document.createElement('a'),
{ href: URL.createObjectURL(blob), download: 'name.txt' }
).click()
此外,您不能使用 Angular 的 HTTP 服务,因为它们使用旧的 XMLHttpRequest
相反,它不能给你一个像 fetch
这样的 ReadableStream从 response.body
开始所以我的建议是改用 Fetch API。
关于javascript - 使用 StreamSaver.js 流式传输大型 blob 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67776919/