由于 CORS,使用 createPresignedPost 或 getPresignedUrl 将 formData 文件从客户端上传到 S3 失败

Uploading formData file from client to S3 using createPresignedPost or getPresignedUrl fails due to CORS

我正在使用 React 网络应用程序并尝试将文件上传到 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'

我已在存储桶配置中正确设置权限 -> CORS json:

[
    {
        "AllowedHeaders": [
            "*",
            "Content-*"
        ],
        "AllowedMethods": [
            "HEAD",
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "*"
        ]
    }
]

我还在代码中验证了存储桶名称。

我试过:

我已经尝试了所有方法并浏览了数十篇文章 (1, 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);
});

在这里我们可以测试从

生成的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": []

经过无数小时的深入研究,我发现了问题所在。
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();

未配置bucket region返回的错误是CORS,真是令人困惑和误导。