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

Azure Blob Storage上传大Blob时如何延长SAS token有效期且不丢失上传进度

可行方案(最低复杂度,无需修改后端逻辑,不丢失上传进度)

核心思路

利用@azure/storage-blob V12 SDK 内置的动态凭证能力,传入可自动刷新有效SAS的自定义凭证,SDK会自动处理上传过程中的凭证刷新,已上传成功的分块不会因为SAS过期失效。

Azure Blob存储的分块上传逻辑中,未提交的分块会和目标Blob绑定、保留7天,仅和存储账户的资源关联,和之前用来上传分块的SAS有效期无关,只要新的SAS对目标Blob有写入权限,就可以直接续传剩余分块,不会丢失已上传进度。

具体实现步骤

  • 前端实现SAS缓存与刷新逻辑,避免频繁请求后端接口
// 全局缓存当前使用的SAS和对应的过期时间
let cachedSas = null;
let sasExpireTimestamp = 0;

async function getValidSas(blobName) {
  const now = Date.now();
  // 提前30秒刷新SAS,避免临界时间节点请求失败
  if (cachedSas && now < sasExpireTimestamp - 30 * 1000) {
    return cachedSas;
  }
  // 调用现有后端接口获取指定Blob的SAS,不需要修改原有后端逻辑
  const resp = await fetch(`/api/get-blob-sas?blobName=${encodeURIComponent(blobName)}`);
  const { sasToken, expiresOn } = await resp.json();
  cachedSas = sasToken;
  sasExpireTimestamp = new Date(expiresOn).getTime();
  return cachedSas;
}
  • 实现符合SDK规范的动态SAS凭证类
class DynamicSasCredential {
  constructor(blobName) {
    this.blobName = blobName;
  }
  // 实现SDK要求的getToken方法,每次请求前SDK会自动调用该方法获取有效凭证
  async getToken() {
    const validSas = await getValidSas(this.blobName);
    // 处理SAS前缀,返回符合SDK要求的格式
    const formatSas = validSas.startsWith('?') ? validSas.slice(1) : validSas;
    return { token: formatSas, expiresOnTimestamp: sasExpireTimestamp };
  }
}
  • 构造BlockBlobClient执行上传,原有上传逻辑无需修改
import { BlockBlobClient, newPipeline } from '@azure/storage-blob';

async function uploadLargeFile(blobName, file) {
  // 用自定义动态凭证构造请求管道
  const uploadPipeline = newPipeline(new DynamicSasCredential(blobName), {
    // 可保留你原有配置,比如重试策略、超时时间等
    retryOptions: { maxTries: 4 }
  });
  // 注意这里用不带SAS的原始Blob地址
  const blobBaseUrl = `https://${你的存储账户名}.blob.core.chinacloudapi.cn/${你的容器名}/${encodeURIComponent(blobName)}`;
  const blockBlobClient = new BlockBlobClient(blobBaseUrl, uploadPipeline);
  
  // 完全复用你原有uploadData逻辑即可,不需要调整分块、并发配置
  return await blockBlobClient.uploadData(file, {
    blockSize: 4 * 1024 * 1024, // 你原有分块大小配置
    concurrency: 5, // 你原有并发数配置
    onProgress: (progress) => console.log(`已上传字节数:${progress.loadedBytes}`)
  });
}

方案优势

  • 改造成本极低:仅需要调整前端BlockBlobClient的初始化逻辑,原有上传逻辑、后端SAS生成接口完全不需要修改
  • 自动保留进度:SDK内部会自动跟踪已上传成功的分块,不会重复上传,无需额外开发进度记录逻辑
  • 安全性不变:仍然保持原有短有效期SAS的安全策略,不会因为大文件上传刻意延长SAS有效期

可选增强:支持页面刷新后续传

如果需要支持用户刷新页面后仍然能从断点续传,可以在上传前先查询服务端已存在的未提交分块,跳过已上传的部分:

// 上传前先获取当前Blob已上传的未提交分块列表
const blockList = await blockBlobClient.getBlockList('uncommitted');
const uploadedBlockIds = new Set(blockList.uncommittedBlocks.map(block => block.name));
// 拆分文件生成块ID时,跳过已存在于uploadedBlockIds中的块即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:09:02