You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java客户端通过API Gateway向S3上传二进制文件异常咨询

解决API Gateway上传二进制文件后显示为字节字符串的问题

你的问题核心在于把二进制数据编码成Base64字符串提交,导致API Gateway和S3将编码后的字符串当作原始内容存储,而非解析还原二进制数据。以下是具体解决方案:

1. 直接提交原始二进制数据

放弃Base64编码步骤,将读取到的byte[]直接作为请求体发送,避免字符串转换带来的编码问题。注意如果你的HttpUtils2.invokeHttpRequest仅支持String类型请求体,需要替换为支持二进制请求的HTTP客户端(比如Apache HttpClient、OkHttp)。

2. 修正请求头与签名计算

  • 设置正确的Content-Type:根据文件类型指定(如图片用image/jpeg、image/png,通用二进制用application/octet-stream),告知服务端请求体的类型。
  • 重新计算x-amz-content-sha256:签名用的哈希值必须基于原始二进制数据计算,而非Base64编码后的字符串。

修改后的代码示例

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class S3Uploader {
    public static void main(String[] args) throws Exception {
        String fileToUpload = "/path/to/your/image.jpg";
        String endpointUrl = "your-api-gateway-endpoint";
        String regionName = "your-region";
        String aws_access_key_id = "your-access-key";
        String aws_secret_access_key = "your-secret-key";

        byte[] data = Files.readAllBytes(Paths.get(fileToUpload));
        // 根据文件类型设置Content-Type,可通过文件后缀动态判断
        String contentType = "image/jpeg";

        Map<String, String> headers = new HashMap<>();
        // 基于原始二进制计算SHA-256哈希
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(data);
        String contentHashString = Base64.getEncoder().encodeToString(hashBytes);

        headers.put("x-amz-content-sha256", contentHashString);
        headers.put("x-amz-storage-class", "REDUCED_REDUNDANCY");
        headers.put("Content-Type", contentType);

        AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader(endpointUrl, "PUT", "execute-api", regionName);
        String authorization = signer.computeSignature(headers, null, contentHashString, aws_access_key_id, aws_secret_access_key);
        headers.put("Authorization", authorization);

        // 使用Apache HttpClient发送二进制请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPut httpPut = new HttpPut(endpointUrl);
        // 添加请求头
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            httpPut.addHeader(entry.getKey(), entry.getValue());
        }
        // 设置二进制请求体
        httpPut.setEntity(new ByteArrayEntity(data));

        CloseableHttpResponse response = httpClient.execute(httpPut);
        String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        // 处理响应
        System.out.println("Response: " + responseBody);

        httpClient.close();
        response.close();
    }
}

3. 检查API Gateway配置

  • 进入API Gateway控制台,找到对应的PUT方法,在集成请求中设置Content Handling为Passthrough,确保二进制数据不被转换为文本。
  • 如果使用了映射模板,删除对请求体的字符串转换逻辑,保证二进制数据直接透传到S3。

内容的提问来源于stack exchange,提问作者pavants

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:25:32