javascript - 使用 StreamSaver.js 流式传输大型 blob 文件

标签 javascript angular angular-httpclient

我正在尝试使用 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-TypeContent-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。

https://github.com/angular/angular/issues/36246

关于javascript - 使用 StreamSaver.js 流式传输大型 blob 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67776919/

相关文章:

javascript - 使用 javascript 看不到一些 cookie

javascript - 如何使用 TypeScript 和 Angular 2 向 ng2-ckeditor 添加插件?

angular - 我们可以有两个具有相同选择属性的 ng-content 吗?

从 API 获取数据时,Angular 5 类型 'Observable<{}>' 无法分配给类型错误

angular - 如何使用 Angular 5 对 HTTP GET 响应进行排序以一次获取一个元素

javascript - 停止错误关闭的 Angular http Observable 流

javascript - PHP 当用户选中复选框时清除文本框

javascript - LoopBack 自动迁移调用顺序

javascript - YouTube 播放器 API - 搜索然后播放

angular - angular2 中的 ng2-toastr - 不工作?