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

如何提升NestJS+Angular向Amazon S3上传50GB数据的速度?

提升Amazon S3大文件批量上传速度的优化方案

核心架构优化:跳过后端中转,前端直接传S3(优先级最高)

当前流程是Angular → 后端服务器 → S3,文件经过两次传输,严重浪费带宽和时间。改用S3预签名URL方案,让前端直接和S3交互,是提升速度最有效的方式:

  • 后端新增接口:生成S3分块上传的预签名URL(包含初始化上传、上传分块、完成上传的权限)
  • Angular端逻辑调整:
    1. 调用后端接口获取预签名信息
    2. 直接在前端完成分块上传到S3(无需经过后端中转)
    3. 所有分块上传完成后,调用后端接口写入数据库记录
  • 优势:减少一次网络传输,前端可充分利用浏览器并发能力,后端仅处理鉴权和数据库操作,资源占用大幅降低

现有代码逻辑修复(若暂时无法调整架构)

1. 修复分块上传的重试逻辑

原上传函数中重试逻辑存在两处致命错误:

  • 判断条件写反:if (!failedParts.length) 应该改为 if (failedParts.length)(只有当有失败块时才重试)
  • 分块切片参数错误:重试时需按块编号正确截取文件片段
  • 重试时未返回Promise,导致无法等待重试完成

修复后的关键代码片段:

// 收集失败块的partNumber(需确保uploadPart抛出错误时携带partNumber)
const failedParts = parts
  .filter((part) => part.status === "rejected")
  .map((part: any) => ({
    partNumber: part.reason.partNumber,
    reason: part.reason
  }));

// 重试失败的块
let retriedParts = [];
if (failedParts.length) {
  retriedParts = await Promise.all(
    failedParts.map((failedItem) => {
      const partNumber = failedItem.partNumber;
      return this.uploadPart(
        file.originalname,
        file.buffer.slice((partNumber - 1) * chunkSize, partNumber * chunkSize),
        uploadId,
        partNumber,
        bucket
      );
    })
  );
  // 合并成功块与重试成功块
  succeededParts = [...succeededParts, ...retriedParts];
}

2. 调整分块大小

当前分块大小设为5MB(代码中1024 * 1024 * 5),建议调整为16MB或32MB:

  • S3分块上传最小块为5MB(最后一块除外),更大的块能减少API调用次数,降低网络开销
  • 修改代码:const chunkSize = 1024 * 1024 * 16; // 16MB

3. 限制后端并发处理数

原代码用Promise.all同时处理所有文件,易导致服务器内存、CPU过载,建议添加并发限制:

// 引入p-limit库实现并发控制(需先安装:npm install p-limit)
import pLimit from 'p-limit';
const limit = pLimit(15); // 限制同时处理15个文件,可根据服务器配置调整

// 替换原forEach逻辑
const allPromises = photos.map(photo => limit(async () => {
  let file = new ChangeFileName().changeName(photo);
  const response = await this.s3fileUploadService.upload(file, `event-gallery-photos/${request.event_id}`);
  if (response.Location) {
    await this.eventPhotoEntity.save({
      studio_id: request.studio_id,
      client_id: request.client_id,
      event_id: request.event_id,
      file_name: file.originalname,
      original_name: file.userFileName,
      file_size: file.size
    });
  }
}));

return Promise.all(allPromises)
  .then(() => new ResponseFormatter(HttpStatus.OK, "Created successfully"))
  .catch(() => new ResponseFormatter(HttpStatus.INTERNAL_SERVER_ERROR, "Something went wrong", {}));

Angular端优化

  1. 并行上传而非串行:原代码循环依次调用API,改为分批次并行上传(浏览器同一域名默认并发数为6,可一次传6个,完成后再传下一批)
  2. 启用HTTP/2:后端配置HTTP/2,支持多路复用,提升并发请求效率
  3. 文件进度监控:添加上传进度回调,避免用户等待焦虑,同时可及时中断异常上传

S3配置验证

  1. 确认Transfer Acceleration端点正确使用:上传时必须使用S3加速域名(格式:bucket-name.s3-accelerate.amazonaws.com),而非普通S3域名
  2. 开启S3智能分层:针对大文件存储,智能分层可自动优化存储性能,间接提升上传后的数据访问效率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:51:18