由于 CORS,使用 createPresignedPost 或 getPresignedUrl 将 formData 文件从客户端上传到 S3 失败
Posted
技术标签:
【中文标题】由于 CORS,使用 createPresignedPost 或 getPresignedUrl 将 formData 文件从客户端上传到 S3 失败【英文标题】:Uploading formData file from client to S3 using createPresignedPost or getPresignedUrl fails due to CORS 【发布时间】:2021-05-03 22:12:21 【问题描述】:我正在使用 React Web 应用程序并尝试将文件上传到 AWS S3。
我在本地 (localhost:3000
) 和部署到生产环境(Vercel 无服务器功能)时都尝试了所有方法。
我首先使用 fetch 来检索文件上传的预签名 url,效果很好:
module.exports = async (req, res) =>
let fileName, fileType = req.body;
const post = await s3.createPresignedPost(
Bucket: BUCKET_NAME,
Fields:
key: fileName
,
ContentType: fileType,
Expires: 60
);
res.status(200).json(post);
然后,在第二次获取中:
await fetch(url, method: 'POST', body: formData
我明白了:
fetch has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
我已经在存储桶配置中正确设置了 Permissions -> CORS json:
[
"AllowedHeaders": [
"*",
"Content-*"
],
"AllowedMethods": [
"HEAD",
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"*"
]
]
我还在我的代码中验证了存储桶名称。
我试过了:
getPresignedUrl
& createPresignedPost
都可以生成网址
PUT
和 POST
都请求
在提取请求中设置标头(Content-Type
、x-amz-acl
)
使用不同的CORS jsons,允许所有来源,暴露不同的头文件,允许所有方法(包括HEAD
,允许不同的头文件(如"Content-*"
)
为不同的用户配置不同的权限(特别是我需要的,所有 S3 权限等)
Settings bucket policy
每次尝试前清除 Chrome 的缓存(使用硬重载)或通过 code 进行
我已经尝试了所有方法并阅读了数十篇文章(1、2)并在此处浏览问题 - 但它仍然无法正常工作。不在本地,也不在生产中。
【问题讨论】:
我找不到具体问题。但是,我可以提供一个我刚刚尝试过的可行解决方案作为答案。 【参考方案1】:经过无数小时的研究,我找到了问题所在。
CORS 错误的原因是我没有在初始 AWS.config.update
配置设置中包含 region
。
一旦我添加了region
键,CORS 错误就解决了:
const AWS = require('aws-sdk');
AWS.config.update(
accessKeyId: 'XXXXX',
secretAccessKey: 'XXXXXX',
region: 'us-west-2', // Must be the same as your bucket
);
const s3Client = new AWS.S3();
未配置存储桶区域返回的错误是CORS,真是令人困惑和误导。
【讨论】:
【参考方案2】:确保文件名与Key
完全匹配
const bucketParms =
Bucket: "sample-temp-bucket",
Key: "HeadShot.jpg",
Expires: 3600,
;
s3.getSignedUrl("putObject", bucketParms, (error, url) =>
if (error) console.log("error", error);
if (url) console.log("url", url);
);
这里我们可以测试postman or curl生成的url
然后我们可以进行 http PUT
调用。
this.http
.put(
"https://sample-temp-bucket.s3.amazonaws.com/HeadShot.jpg?X-Amz-Algorithm=AWS4-HMAC....",
formData
)
.subscribe((response) =>
console.log("response received is ", response);
);
而 CORS,ExposeHeaders
的通配符不接受(至少来自控制台),它只使用空数组 "ExposeHeaders": []
【讨论】:
验证了所有这些东西,但我仍然遇到同样的错误:Access to fetch at 'https://s3.amazonaws.com/bucket-name' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. FileUpload.jsx:34 POST https://s3.amazonaws.com/bucket-name net::ERR_FAILED
以上是关于由于 CORS,使用 createPresignedPost 或 getPresignedUrl 将 formData 文件从客户端上传到 S3 失败的主要内容,如果未能解决你的问题,请参考以下文章