Skip to content

如何解决上传文件到S3时返回400错误

0

this is my code:
const Aws::String bucket = "cct-.........-test";
const Aws::String filename = "tc.wav";
Aws::Auth::AWSCredentials credentials("................................", "................................");
Aws::S3::S3ClientConfiguration config;
config.region = "us-east-1";
config.scheme = Aws::Http::Scheme::HTTP;
config.useVirtualAddressing = false;
config.endpointOverride = "oss.........com";
std::shared_ptrAws::IOStream inputData = Aws::MakeSharedAws::FStream("SampleAllocationTag", filename.c_str(), std::ios_base::in | std::ios_base::binary);
if (!*inputData) { std::cerr << "Error unable to read file " << filename << std::endl; return 1; }
struct stat file_stat;
stat(filename.c_str(), &file_stat);
auto filesize = file_stat.st_size;
inputData->seekg(0, std::ios::beg);
Aws::S3::Model::PutObjectRequest request;
request.SetBucket(bucket);
request.SetKey(filename);
request.SetBody(inputData);
request.SetContentLength(filesize);
request.SetContentType("audio/wav");
Aws::S3::S3Client s3_client(credentials, config, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Always, false);
Aws::S3::Model::PutObjectOutcome outcome = s3_client.PutObject(request);
if (!outcome.IsSuccess()) {
std::cerr << "Error: PutObject: " << outcome.GetError().GetMessage() << " | " << outcome.GetError().GetExceptionName() << std::endl;
}
the log output http400
[INFO] 2025-06-01 07:02:25.684 Aws_Init_Cleanup [.................] Initiate AWS SDK for C++ with Version:1.11.577
[DEBUG] 2025-06-01 07:02:25.812 CURL [................] (HeaderOut) PUT /cct-record-test/tc.wav HTTP/1.1
Accept: /
amz-sdk-invocation-id: 9BC5ABBE-19A2-417E-A64E-097C6AC5958C
amz-sdk-request: attempt=1
authorization: AWS4-HMAC-SHA256 Credential=......................., SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-encoding;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-trailer, Signature=94a14a5679eb9a841eb906e47583e535291b3f1df5541e50c5ba98e5bf1a9da0 content-encoding: aws-chunked
content-type: audio/wav
host: oss.17usoft.com
transfer-encoding: chunked
user-agent: aws-sdk-cpp/1.11.577 ua/2.1 api/S3 os/Linux#3.10.0-957.21.3.el7.x86_64 lang/c++#C++11 md/aws-crt#0.32.4 md/arch#x86_64 md/GCC#9.3.1 m/D,W,Z,b,P
x-amz-content-sha256: STREAMING-UNSIGNED-PAYLOAD-TRAILER
x-amz-date: 20250601T070225Z
x-amz-decoded-content-length: 1520460
x-amz-trailer: x-amz-checksum-crc64nvme
Expect: 100-continue
[DEBUG] 2025-06-01 07:02:25.847 CURL [...........] (HeaderIn) HTTP/1.1 400 Bad Request
[ERROR] 2025-06-01 07:02:25.847 AWSXmlClient [...........] HTTP response code: 400
Resolved remote host IP address: 123..........7
Request ID:
Exception name:
Error message: No response body.
6 response headers:
connection : close
content-length : 0
date : Sun, 01 Jun 2025 07:02:25 GMT
server : Lego Server
x-cache-lookup : Return Directly
x-nws-log-uuid : 16880156800366600205
[WARN] 2025-06-01 07:02:25.847 AWSClient [.............] If the signature check failed. This could be because of a time skew. Attempting to adjust the signer.
[DEBUG] 2025-06-01 07:02:25.847 AWSClient [.....................] Server time is Sun, 01 Jun 2025 07:02:25 GMT, while client time is Sun, 01 Jun 2025 07:02:25 GMT
Can someone help me see where the problem is? I can upload successfully using the aws cli tool, which means the server, KEY, and endpoint are correct but my code doesn't work. I can't see more useful information from the log.

asked 10 months ago282 views
3 Answers
0

您遇到的 S3 上传 400 错误可能有几个原因。根据您提供的代码和日志,我注意到几个可能的问题点:

  1. 端点配置问题:您使用了自定义端点 oss.........com,但同时设置了 config.useVirtualAddressing = false。S3 默认使用虚拟寻址风格,如果您的端点需要路径风格寻址,这个设置是正确的,但可能与您的端点要求不匹配。

  2. 认证问题:日志中显示 "If the signature check failed. This could be because of a time skew",这表明可能存在签名验证失败的问题。虽然日志显示客户端和服务器时间似乎一致,但签名计算可能仍有问题。

  3. 硬编码凭证:您在代码中直接硬编码了 AWS 凭证,这不是最佳实践。在 Lambda 或其他 AWS 服务中运行时,应该使用执行角色的权限而不是硬编码凭证。

  4. 区域与端点不匹配:您设置了 us-east-1 区域,但使用了自定义端点。确保这两者是兼容的。

  5. HTTP 协议:您使用了 Aws::Http::Scheme::HTTP 而不是 HTTPS,S3 通常需要 HTTPS 连接。

建议的解决方案:

  1. 尝试使用 HTTPS 而不是 HTTP:
config.scheme = Aws::Http::Scheme::HTTPS;
  1. 检查虚拟寻址设置是否与您的端点兼容:
config.useVirtualAddressing = true; // 或根据您的端点要求设置
  1. 如果在 AWS Lambda 中运行,移除硬编码凭证,让代码使用 Lambda 执行角色:
Aws::S3::S3Client s3_client(config);
  1. 确保区域设置与您的端点匹配。

  2. 检查您的桶名称和文件路径是否正确。

由于您提到可以使用 AWS CLI 成功上传,这表明权限和端点配置基本正确。问题可能在于 SDK 的具体配置或签名计算方式与 CLI 不同。尝试以上建议,特别是切换到 HTTPS 和调整虚拟寻址设置,可能会解决您的问题。
Sources
Use PutObject with an AWS SDK or CLI - Amazon Simple Storage Service
The request signature we calculated does not match the signature you provided. Check your key and signing method. I get this error only when i use lambda function. Their is no issue in local server | AWS re:Post
Use PutObject with an AWS SDK or CLI - AWS SDK Code Examples

answered 10 months ago
0

if use

config.useVirtualAddressing = true;

then

Error: PutObject: curlCode: 6, Couldn't resolve host name; Details: Could not resolve host: cct--test.oss..com; Unknown error

The same return when using HTTPS, and the awl cli test uses the http address.

answered 10 months ago
0

The time recorded in the logs is GMT, and the time on my local machine is CST,
which could be a problem, but I don't know how unify the time to CST,
the logs output by the aws cli are also CST time.

answered 10 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.