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

Apache HttpClient返回Bad Request,请求排查配置问题

Apache HttpClient配置S3表单上传返回Bad Request问题排查

问题背景

已导出可正常运行的Postman POST请求JSON,按该请求配置Apache HttpClient后,始终收到Bad Request响应,需排查配置问题。

Postman导出的请求内容

{
  "info": {
    "_postman_id": "eae7c603-8b49-496f-9f71-a16b475f34ce",
    "name": "Upload Documents",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_exporter_id": "14164917"
  },
  "item": [
    {
      "name": "Upload a supporting document",
      "request": {
        "method": "POST",
        "header": [],
        "body": {
          "mode": "formdata",
          "formdata": [
            { "key": "Key", "value": "someValue", "type": "text" },
            { "key": "X-Amz-Algorithm", "value": "AWS4-HMAC-SHA256", "type": "text" },
            { "key": "X-Amz-Credential", "value": "someValue", "type": "text" },
            { "key": "X-Amz-Date", "value": "20220802T142430Z", "type": "text" },
            { "key": "X-Amz-Security-Token", "value": "someValue", "type": "text" },
            { "key": "Policy", "value": "someValue", "type": "text" },
            { "key": "X-Amz-Signature", "value": "someValue", "type": "text" },
            { "key": "X-Amz-Meta-X-Swan-Supporting-Document-Id", "value": "someValue", "type": "text" },
            { "key": "file", "type": "file", "src": "/path/test.pdf" }
          ]
        },
        "url": {
          "raw": "https://s3.eu-west-1.amazonaws.com/document-sandbox",
          "protocol": "https",
          "host": [ "s3", "eu-west-1", "amazonaws", "com" ],
          "path": [ "document-sandbox" ]
        }
      },
      "response": []
    }
  ]
}

现有Apache HttpClient代码

private static CloseableHttpResponse upload(String url, Map<String, String> requestParameters, File file) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);

        FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);

        try {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, fileBody.getFilename());
            requestParameters.forEach((key, value) -> builder.addTextBody(key, value, ContentType.TEXT_PLAIN));
            httpPost.setEntity(builder.build());

            CloseableHttpResponse response = httpClient.execute(httpPost);
            httpClient.close();
            return response;
        } catch (Exception e) {
            throw new RuntimeException("Uploading document failed, error: " + e.getMessage());
        }
    }

问题分析与修复

1. 表单字段顺序错误

S3预签名表单上传对字段顺序有严格要求,必须先传递所有文本参数,最后传递文件字段。你的代码中先添加了file字段,再循环添加文本参数,顺序与Postman完全相反,这会导致S3签名验证失败,返回Bad Request。

2. 文本字段ContentType设置不当

Postman中的文本字段使用form-data默认的文本类型,而代码中指定了ContentType.TEXT_PLAIN,会给文本字段额外添加Content-Type: text/plain头,与Postman的请求格式不一致,可能触发S3的验证逻辑报错。

3. 客户端资源关闭时机错误

代码在执行请求后立刻关闭httpClient,返回的CloseableHttpResponse会因为客户端已关闭而无法正常读取响应体,不利于排查具体错误原因。

修复后的代码

private static CloseableHttpResponse upload(String url, Map<String, String> requestParameters, File file) {
    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
        HttpPost httpPost = new HttpPost(url);
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();

        // 先添加所有文本参数,保持与Postman一致的顺序
        requestParameters.forEach((key, value) -> builder.addTextBody(key, value));
        // 最后添加文件字段
        builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, file.getName());

        httpPost.setEntity(builder.build());
        return httpClient.execute(httpPost);
    } catch (Exception e) {
        throw new RuntimeException("Uploading document failed, error: " + e.getMessage());
    }
}

说明:

  • 使用try-with-resources自动管理CloseableHttpClient的生命周期,避免提前关闭导致响应无法读取
  • 调整字段顺序,先添加所有文本参数,最后添加文件
  • 去掉addTextBody的ContentType.TEXT_PLAIN参数,使用默认的form-data文本类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:09:20