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

Java客户端向FastAPI发送Multipart表单数据时遇边界字符未找到错误

问题:Java客户端向FastAPI上传Multipart表单数据报错

现象描述

尝试从Java客户端向Python FastAPI服务器上传文件并发送文本参数时,遇到错误:

Did not find boundary character 54 at index 4

  • 可正常工作的CURL命令:
curl -X POST \
     -F "files=@/path/to/my/file" \
     -F "param1=someValue" \
     "http://localhost:8000/my_endpoint"
  • 可正常工作的Python测试代码:
with open(input_file, "rb") as file:
    response = client.post(
        url="/my_endpoint",
        data={"param1": "someValue"},
        files=[("files", file)],
    )
  • Java代码执行后,FastAPI服务器日志显示:
Did not find boundary character 121 at index 4
INFO:     127.0.0.1:60803 - "POST /transcribe HTTP/1.1" 400 Bad Request
  • 移除Java代码中的Content-Type头后,服务器返回422 Unprocessable Entity错误。

问题代码

Java请求构建代码:

String boundary = UUID.randomUUID().toString();
HttpRequest httpRequest = HttpRequest.newBuilder()
    .uri(URI.create(myUrl))
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .version(HttpClient.Version.HTTP_1_1)
    .POST(HttpRequest.BodyPublishers.ofByteArray(createFormData(multipartFile)))
    .build();
HttpResponse<String> resp = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

表单数据构建方法:

private byte[] createFormData(MultipartFile multipartFile) throws IOException {
    HttpEntity httpEntity = createMultipartFile(multipartFile);
    return getByteArray(httpEntity);
}

public HttpEntity createMultipartFile(MultipartFile multipartFile) {
    try {
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();

        byte[] fileBytes = multipartFile.getBytes();
        ByteArrayBody fileBody = new ByteArrayBody(fileBytes, ContentType.DEFAULT_BINARY, multipartFile.getName());
        builder.addPart("files", fileBody);

        builder.addPart("param1", new StringBody("someValue", ContentType.TEXT_PLAIN));

        return builder.build();
    } catch (IOException e) {
        throw new MyException(e);
    }
}

public byte[] getByteArray(HttpEntity multipartEntity) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        multipartEntity.writeTo(baos);
        return baos.toByteArray();
    } catch (IOException e) {
        throw new MyException(e);
    }
}

错误原因

手动设置的boundary和MultipartEntityBuilder自动生成的边界不匹配。MultipartEntityBuilder默认会生成随机边界,而请求头里指定了另一个完全不同的边界值,导致FastAPI解析时找不到对应的分隔符,抛出边界匹配错误。

移除自定义Content-Type头后,Java的HttpClient不会自动添加包含正确边界的multipart/form-data头,FastAPI无法识别请求格式,因此返回422错误。

解决方案

方法1:复用MultipartEntityBuilder生成的边界值

从构建好的HttpEntity中获取实际使用的边界,再设置到请求头里:

// 构建multipart实体
HttpEntity multipartEntity = createMultipartFile(multipartFile);
// 获取实体自带的Content-Type头(包含自动生成的boundary)
ContentType contentType = ContentType.getOrDefault(multipartEntity);
String contentTypeHeader = contentType.toString();

// 构建请求
HttpRequest httpRequest = HttpRequest.newBuilder()
    .uri(URI.create(myUrl))
    .header("Content-Type", contentTypeHeader)
    .version(HttpClient.Version.HTTP_1_1)
    .POST(HttpRequest.BodyPublishers.ofByteArray(getByteArray(multipartEntity)))
    .build();
HttpResponse<String> resp = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

同时删除原来手动生成boundary的代码行:String boundary = UUID.randomUUID().toString();

方法2:手动指定MultipartEntityBuilder的边界值

如果想自己控制边界值,需要把生成的boundary传给MultipartEntityBuilder,确保请求头和实体内容的边界一致:

修改createMultipartFile方法,添加边界参数:

public HttpEntity createMultipartFile(MultipartFile multipartFile, String boundary) {
    try {
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        // 设置手动指定的边界
        builder.setBoundary(boundary);

        byte[] fileBytes = multipartFile.getBytes();
        ByteArrayBody fileBody = new ByteArrayBody(fileBytes, ContentType.DEFAULT_BINARY, multipartFile.getName());
        builder.addPart("files", fileBody);

        builder.addPart("param1", new StringBody("someValue", ContentType.TEXT_PLAIN));

        return builder.build();
    } catch (IOException e) {
        throw new MyException(e);
    }
}

修改请求构建代码:

String boundary = UUID.randomUUID().toString();
HttpEntity multipartEntity = createMultipartFile(multipartFile, boundary);

HttpRequest httpRequest = HttpRequest.newBuilder()
    .uri(URI.create(myUrl))
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .version(HttpClient.Version.HTTP_1_1)
    .POST(HttpRequest.BodyPublishers.ofByteArray(getByteArray(multipartEntity)))
    .build();
HttpResponse<String> resp = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

验证说明

两种方法都能保证请求头中的边界值和实体内容里的分隔符完全一致,FastAPI可正确解析Multipart表单数据,不会再出现边界匹配错误或422格式错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:50:08