Angular上传文件至Azure Blob Storage遇CORS错误求助
Angular上传Azure Blob Storage时的CORS错误排查
问题描述
从Angular上传文件至Azure Blob Storage时触发CORS错误,但相同的Azure存储账户配置在ASP.NET中可正常工作。测试阶段直接使用固定SAS Token而非动态生成,错误截图如下:
实现代码
环境配置文件
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
相关产品推荐
相关产品推荐

