Angular使用预签名URL上传文件至S3时遇CORS问题求助
Angular通过预签名URL向DigitalOcean Spaces上传文件遇CORS错误问题
我在Angular前端通过后端生成的预签名URL向DigitalOcean Spaces(兼容S3)上传文件时遇到CORS错误,但相同请求在Postman里能正常执行。
错误信息
Access to XMLHttpRequest at 'https://fra1.digitaloceanspaces.com/my-test-s3-bucket/a9da491a-cfaa-4532-bae6-43a515f5e657.doc?AWSAccessKeyId=DO00CPCLULU4MB9RHW2A&Content-Type=application%2Fmsword&Expires=1704439698&Signature=GT1PLU6sCqCeLe9nnb5GExs%2BWj4%3D' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
Angular上传代码
async upload(links: Sections<string[]>, files: Sections<File[]>) { const h = (file: File) => ({ 'Content-Type': file.type }); console.log("links: ", links); console.log("files: ", files); return await Promise.all([ ...files.information.map((file, i) => this.http.put(links.information[i], file, { headers: h(file) }).toPromise() ), ]); }
存储桶CORS配置
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <ExposeHeader>ETag</ExposeHeader> <AllowedHeader>*</AllowedHeader> </CORSRule> <CORSRule> <AllowedOrigin>http://localhost:4200</AllowedOrigin> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <ExposeHeader>ETag</ExposeHeader> <AllowedHeader>*</AllowedHeader> </CORSRule>
排查与解决步骤
- 核对预签名URL生成逻辑:后端生成预签名URL时,必须将请求中使用的
Content-Type参数纳入签名范围,同时确保指定的HTTP方法为PUT。如果签名参数和实际请求不匹配,即使桶的CORS配置正确,也会触发CORS错误。 - 简化并验证CORS配置:当前配置中两个规则存在重复,保留任意一个即可(比如仅保留允许
http://localhost:4200的规则)。DigitalOcean Spaces的CORS配置修改后需要1-2分钟生效,修改后等待片刻再测试。也可以显式添加<AllowedHeader>Content-Type</AllowedHeader>,避免通配符匹配的潜在问题。 - 调整Angular请求细节:避免文件类型获取不准确导致的头信息不匹配,可以尝试用
'application/octet-stream'作为兜底,或者直接从预签名URL的查询参数中提取Content-Type值来设置请求头,确保和签名时的参数完全一致。也可以添加observe: 'response'选项查看完整响应头,确认CORS头部是否返回:this.http.put(links.information[i], file, { headers: h(file), observe: 'response' }).toPromise() - 检查浏览器预检请求:打开浏览器开发者工具的网络面板,查看OPTIONS预检请求的响应状态和返回头。如果预检请求没有返回
Access-Control-Allow-Origin等CORS头部,说明桶的CORS配置未正确生效。
内容的提问来源于stack exchange,提问作者Илья Никитин
相关产品推荐
相关产品推荐

