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

使用JSZip压缩大量文件时浏览器崩溃问题求助

优化大文件目录压缩上传的解决方案

针对你遇到的内存过载导致浏览器崩溃的问题,核心原因是JSZip默认会将所有文件内容加载到内存中生成完整ZIP Blob,当总容量达到数GB时,内存占用会远超浏览器承载极限。以下是几个实用的优化方案:

方案一:改用流式压缩库+S3分段上传(推荐)

替换JSZip为@zip.js/zip.js,它支持流式压缩——边读取文件、边压缩、边输出数据,无需在内存中存储完整ZIP文件。结合S3的分段上传API,彻底规避内存过载问题。

代码示例:

import { ZipWriter, BlobReader } from "@zip.js/zip.js";

// 1. 初始化S3分段上传,获取uploadId(需调用S3 CreateMultipartUpload API)
const uploadId = await initiateS3MultipartUpload("your-bucket", "target-zip.zip");
const parts = [];
let partNumber = 1;

// 2. 自定义ZipWriter输出流,直接将压缩片段上传到S3
const zipWriter = new ZipWriter({
  async writeUint8Array(array) {
    // 上传当前压缩片段到S3
    const partETag = await uploadS3Part(
      "your-bucket", 
      "target-zip.zip", 
      uploadId, 
      partNumber++, 
      array
    );
    parts.push({ PartNumber: partNumber - 1, ETag: partETag });
    // 主动释放内存
    array = null;
  },
  async close() {
    // 完成S3分段上传合并
    await completeS3MultipartUpload(
      "your-bucket", 
      "target-zip.zip", 
      uploadId, 
      parts
    );
  }
});

// 3. 逐个处理文件,边读边压缩边上传
for (const file of files) {
  await zipWriter.add(
    file.name, 
    new BlobReader(file), 
    { compression: file.type.includes("image/") ? "STORE" : "DEFLATE" }
    // 图片/视频等已压缩文件直接存储,减少CPU和内存消耗
  );
}

// 4. 完成压缩与上传
await zipWriter.close();

方案二:优化JSZip内存占用(适合中小规模场景)

如果不想更换库,可以通过分批处理+内存释放缓解压力,但对20GB级内容效果有限:

  • 分批加载文件到JSZip,每批生成ZIP片段后立即上传到S3,清空当前批次的内存占用;
  • 生成ZIP时启用streamFiles: true选项(JSZip v3.10+支持),让文件逐个流式写入,而非一次性加载所有内容:
const zip = new JSZip();
const batchSize = 100; // 每批处理100个文件

for (let i = 0; i < files.length; i += batchSize) {
  const batch = files.slice(i, i + batchSize);
  batch.forEach(file => zip.file(file.name, file));
  
  // 生成流式ZIP并上传
  const stream = await zip.generateAsync({ type: "uint8array", streamFiles: true });
  await uploadStreamToS3Chunk(stream, "your-bucket", `temp-part-${i/batchSize}.zip`);
  
  // 清空当前批次内存
  zip.remove(batch.map(f => f.name));
}

// 最后在S3端合并所有临时分片(需调用S3 CopyObject或合并API)
await mergeS3Parts("your-bucket", "target-zip.zip", tempPartNames);

方案三:用IndexedDB暂存文件,减少内存占用

将用户上传的文件暂存到IndexedDB而非内存,压缩时逐个读取内容,处理后立即释放:

// 先将文件存入IndexedDB(省略存储逻辑)
const zip = new JSZip();

for (const fileMeta of filesMeta) {
  // 从IndexedDB读取单个文件Blob
  const fileBlob = await getFileFromIndexedDB(fileMeta.name);
  zip.file(fileMeta.name, fileBlob);
  
  // 释放Blob内存
  URL.revokeObjectURL(fileBlob);
}

// 生成流式ZIP并上传
const stream = await zip.generateAsync({ type: "uint8array", streamFiles: true });
await uploadStreamToS3(stream, "your-bucket", "target-zip.zip");

额外优化点

  • 针对已压缩文件(图片、视频、PDF等),关闭ZIP压缩(设置compression: "STORE"),减少CPU和内存消耗;
  • 用performance.memory(Chrome支持)监控内存占用,当接近阈值时暂停处理,避免崩溃;
  • 所有操作使用异步函数,避免阻塞主线程导致浏览器假死。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:30:44