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

Angular上传文件至Azure Blob Storage遇CORS错误求助

Angular上传Azure Blob Storage时的CORS错误排查

问题描述

从Angular上传文件至Azure Blob Storage时触发CORS错误,但相同的Azure存储账户配置在ASP.NET中可正常工作。测试阶段直接使用固定SAS Token而非动态生成,错误截图如下:
Azure Blob Storage CORS错误

实现代码

环境配置文件

export const environment = {
  "production": false,
  "accountName" : "<accountname>",
  "containerName":"<containername>",
  "key":"<key>"
};

Polyfills配置

(window as any).global = window;
(window as any).process = require( 'process' );
(window as any).Buffer = require( 'buffer' ).Buffer

文件上传方法

async uploadFileToBlob() {
    // generate account sas token
    const accountName = environment.accountName;
    const key = environment.key;

    var str = CryptoJS.HmacSHA256(StringToSign, CryptoJS.enc.Base64.parse(key));
    var sig = CryptoJS.enc.Base64.stringify(str);


    const sasToken = `sp=rac&st=2022-11-21T15:37:13Z&se=2023-12-31T23:37:13Z&spr=https&sv=2021-06-08&sr=c&sig=rYx4JWTcGPVSceUkuxJDSXN8u1%2BbNSFh3A7dYPqw3EA%3D`;
    const containerName = environment.containerName;

    const pipeline = newPipeline(new AnonymousCredential(), {
      "retryOptions": { "maxTries": 4 }, // Retry options
      "userAgentOptions": { "userAgentPrefix": "AdvancedSample V1.0.0" }, // Customized telemetry string
      "keepAliveOptions": {
        // Keep alive is enabled by default, disable keep alive by setting false
        "enable": false
      }
    });

    const blobServiceClient = new BlobServiceClient(`https://${accountName}.blob.core.windows.net?${sasToken}`,
      pipeline)
    const containerClient = blobServiceClient.getContainerClient(containerName)
    if (!containerClient.exists()) {
      console.log("the container does not exit")
      await containerClient.create()

    }
    const client = containerClient.getBlockBlobClient(this.fileName.name)
    const response = await client.uploadData(this.fileName, {
      "blockSize": 4 * 1024 * 1024, // 4MB block size
      "concurrency": 20, // 20 concurrency
      "onProgress": (ev) => console.log(ev),
      "blobHTTPHeaders": { "blobContentType": this.fileName.type }
    })
    console.log(response._response.status)
  }

解决方案

1. 修正Azure Blob CORS配置

确保存储账户的CORS规则覆盖以下要点:

  • 允许的来源:添加Angular应用的域名(如本地开发的http://localhost:4200),测试阶段可临时用*验证
  • 允许的HTTP方法:必须包含OPTIONS(预检请求)、PUT、POST、GET
  • 允许的请求头:包含Content-Type,或直接用*
  • 暴露的响应头:设置为*,确保客户端能读取响应头
  • 最大缓存时长:设置合理值(如3600),减少预检请求频率

2. 修复代码中的权限与逻辑问题

  • SAS Token权限不足:当前SAS的sp=rac仅包含读取、添加、创建权限,缺少**写入(w)**权限,需修改为sp=racw
  • 容器创建权限风险:前端代码中containerClient.create()需要账户级权限,SAS Token通常不具备此权限,建议提前在Azure Portal手动创建容器,移除前端创建逻辑
  • 简化客户端初始化:使用SAS Token时无需手动创建pipeline,直接使用默认构造函数即可

调整后的上传方法示例

async uploadFileToBlob() {
    const accountName = environment.accountName;
    // 修正SAS Token权限,添加写入权限w
    const sasToken = `sp=racw&st=2022-11-21T15:37:13Z&se=2023-12-31T23:37:13Z&spr=https&sv=2021-06-08&sr=c&sig=rYx4JWTcGPVSceUkuxJDSXN8u1%2BbNSFh3A7dYPqw3EA%3D`;
    const containerName = environment.containerName;

    // 简化BlobServiceClient初始化
    const blobServiceClient = new BlobServiceClient(`https://${accountName}.blob.core.windows.net?${sasToken}`);
    const containerClient = blobServiceClient.getContainerClient(containerName);
    
    // 容器提前在Azure Portal创建,移除前端创建逻辑
    // if (!containerClient.exists()) {
    //   console.log("容器不存在");
    //   await containerClient.create();
    // }

    const client = containerClient.getBlockBlobClient(this.fileName.name);
    try {
      const response = await client.uploadData(this.fileName, {
        blockSize: 4 * 1024 * 1024,
        concurrency: 20,
        onProgress: (ev) => console.log(ev),
        blobHTTPHeaders: { blobContentType: this.fileName.type }
      });
      console.log("上传成功,状态码:", response._response.status);
    } catch (error) {
      console.error("上传失败:", error);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:25:26