场景:
getSignedUrl
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { env } from "@/env";
const AWS_REGION = "ap-southeast-2";
const s3Client = new S3Client({
region: AWS_REGION,
credentials: {
accessKeyId: env.AWS_S3_ACCESS_ID,
secretAccessKey: env.AWS_S3_ACCESS_KEY,
},
});
const command = new PutObjectCommand({
Bucket: s3Object.bucket,
Key: s3Object.key,
// I also tried passing the contenttype here to see if it changed anything. But no it didn't.
// ContentType: s3Object.contentType,
// Might need more fields here to refine...
});
// Calculate dynamic expiration time based on file size, user's internet connection speed, etc.
const expiresIn = calculateExpirationTime(s3Object);
const presignedUrl = await getSignedUrl(s3Client, command, { expiresIn });
return presignedUrl;
// Uploads a chunk to the presigned URL
const uploadPart = (opts: {
url: string;
chunk: Blob;
contentType: string;
chunkSize: number;
fileName: string;
maxRetries: number;
}) =>
fetch(opts.url, {
method: "PUT",
body: opts.chunk,
//headers: {
// "Content-Type": opts.contentType,
//},
})
Access to fetch at 'https://mybucket.s3.ap-southeast-2.amazonaws.com/mydoc.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AMZ_VALUE%2Fap-southeast-2%2Fs3%2Faws4_request&X-Amz-Date=20240516T010037Z&X-Amz-Expires=14400&X-Amz-Signature=SIGNATURE&X-Amz-SignedHeaders=host&x-id=PutObject' 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.
OPTIONS 请求已发送并返回为
403 Forbidden
Request Method:
OPTIONS
Status Code:
403 Forbidden
Remote Address:
<IP>:443
Referrer Policy:
strict-origin-when-cross-origin
响应标头:
Content-Type:
application/xml
Date:
Thu, 16 May 2024 01:03:33 GMT
Server:
AmazonS3
Transfer-Encoding:
chunked
X-Amz-Id-2:
<ID>
X-Amz-Request-Id:
<ID>
请求标头:
Accept:
*/*
Accept-Encoding:
gzip, deflate, br, zstd
Accept-Language:
en-US,en;q=0.9
Access-Control-Request-Method:
PUT
Cache-Control:
no-cache
Connection:
keep-alive
Host:
mybucket.s3.ap-southeast-2.amazonaws.com
Origin:
http://localhost:3000
Pragma:
no-cache
Referer:
http://localhost:3000/
Sec-Fetch-Dest:
empty
Sec-Fetch-Mode:
cors
Sec-Fetch-Site:
cross-site
User-Agent:
<AGENT>
我已经正确配置了。我尝试了许多不同的变体,包括在AllowedOrigins中显式定义localhost:3000。
CORS 设置:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"HEAD"
],
"AllowedOrigins": [
"*"
]
}
]
生成预签名 URL 的用户附加了以下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::mybucket",
"arn:aws:s3:::bmybucket/*"
],
"Effect": "Allow"
}
]
}
我已经在这个问题上挣扎了一段时间,并尝试了来自 SO 和 Google 的许多建议。没有一个有效。我有一种感觉,我错过了一些小细节,这让我感到悲伤。
当我在 Postman 中测试 PUT 命令时,出现以下错误,该错误与 COR 错误不同:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>PermanentRedirect</Code>
<Message>The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.</Message>
<Endpoint>s3.amazonaws.com</Endpoint>
<Bucket>mybucket</Bucket>
<RequestId>__ID__</RequestId>
<HostId>__ID__</HostId>
</Error>
事实证明我已经按照书本做了所有事情,这归结为疏忽使用了错误的存储桶名称。
我的 CDK 部署创建了具有唯一名称的存储桶,并且我使用的是我设置的名称。但是,我完全忽略了 AWS 控制台中存储桶的名称。