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 a month ago32 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 a month 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 a month 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 a month 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.