You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular大文件(超1GB)分块直写硬盘下载方案咨询

可行方案说明

要实现大文件分块下载并直接写入硬盘,同时保留使用serverApiService的要求,完全可以做到,核心是结合浏览器流式API和调整现有请求配置,以下是具体实现步骤:


1. 调整downloadFilteredZip方法,支持流式响应

首先需要让请求返回ReadableStream而非完整Blob,这样可以边下载边处理数据,避免内存堆积。如果你的serverApiService是基于AngularHttpClient封装的,只需修改请求配置:

downloadFilteredZip(imageSetId: number, list: Array<string | number>, allSelected: boolean) {
    const offsetFilters = this.getOffsetFilters();
    const areAllSelected = list.includes('all');

    const url = `image-sets/${imageSetId}/archive?${this.serverApiService.rebuildObjectToQuery({
        ...this.filters,
        ...(!areAllSelected && offsetFilters),
        ...(!areAllSelected && !allSelected && { ids: list }),
    })}`;

    // 配置流式响应,通过类型断言绕过TypeScript限制
    return this.serverApiService.get<ReadableStream>(url, { 
        responseType: 'stream' as 'json',
        observe: 'response' // 必须获取完整响应头,用于提取文件名
    });
}

2. 前端修改下载逻辑,用流式API直接写入硬盘

使用浏览器的FileSystem Access API(主流Chrome/Edge支持)直接将分块数据写入本地文件,全程不把完整文件加载到内存:

const list = this.selectionService.getListValue();
const areAllSelected = this.selectionService.getIsAllSelectedValue();

this.loadingText = 'Exporting images...';
this.showLoading = true;
this.absolutePosition = true;

try {
    // 获取流式响应
    const response = await this.projectImagesService.downloadFilteredZip(event.imageSetId, list, areAllSelected).toPromise();
    
    // 解析响应头中的文件名
    const contentDisposition = response.headers.get('Content-Disposition');
    const filename = contentDisposition
        ? contentDisposition.split('filename=')[1].replace(/["']/g, '') // 去除文件名前后的引号
        : `image_set_${event.imageSetId}_${Date.now()}.zip`;

    // 弹出保存文件选择框
    const fileHandle = await window.showSaveFilePicker({
        suggestedName: filename,
        types: [{
            description: '压缩文件',
            accept: { 'application/zip': ['.zip'] }
        }]
    });

    // 创建可写流并将下载流直接管道写入
    const writableStream = await fileHandle.createWritable();
    await response.body?.pipeTo(writableStream);
    await writableStream.close();

    // 结束加载状态
    this.showLoading = false;
    this.absolutePosition = false;
    this.loadingText = 'Uploading...';
} catch (err) {
    console.error('下载失败:', err);
    // 错误处理:重置状态、提示用户
    this.showLoading = false;
    this.absolutePosition = false;
    this.loadingText = 'Uploading...';
}

3. 兼容性与备选方案

  • 浏览器兼容:如果需要支持Safari等暂不支持FileSystem Access API的浏览器,可以退而求其次,用ReadableStream分块拼接Blob(仍会占用部分内存,但比全量加载好),或者结合Service Worker实现后台下载。
  • 后端要求:确保后端启用分块传输(响应头包含Transfer-Encoding: chunked),否则前端无法流式接收数据。

内容的提问来源于stack exchange,提问作者Val

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:47:36