You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Retrofit2无法实现Postman表单编码文件上传功能求助

解决Retrofit2表单文件上传的问题

看起来你在复刻Postman的表单文件上传请求时踩了几个Retrofit2的常见坑,我来帮你梳理问题并给出可行的解决方案。

先拆解下你尝试的三种写法里的核心问题:

  • 第一种写法:仅用@Part("files") RequestBody file传递文件内容,缺少文件名和Content-Disposition头的设置,服务端无法识别这是一个标准的表单文件字段。
  • 第二种写法:同时使用@Multipart注解和@Body MultipartBody,这是冲突的——@Multipart是让Retrofit自动构建多部分表单,而@Body是直接传递完整请求体,两者不能共存,会导致请求结构解析错误。
  • 第三种写法:本身逻辑是对的,但你手动设置的Content-Type头会覆盖Retrofit自动生成的带boundary的multipart/form-data头,导致服务端无法解析分隔的表单内容。

正确的实现步骤

1. 定义Retrofit接口

移除手动设置的Content-Type头,@Multipart注解会自动生成符合规范的请求头:

@Multipart
@POST
Call<I3ClaimsResponse> postDocument(
    @Url String url,
    @Header("Authorization") String token,
    @Part MultipartBody.Part file
);

2. 构建请求体并发起请求

// 1. 获取目标文件对象
File pdfFile = new File("你的文件本地路径");

// 2. 创建RequestBody,指定文件的MIME类型
RequestBody requestFile = RequestBody.create(
    pdfFile,
    MediaType.parse("application/pdf")
);

// 3. 构建MultipartBody.Part,指定表单字段名和文件名
MultipartBody.Part filePart = MultipartBody.Part.createFormData(
    "files",  // 必须和服务端要求的表单字段名完全一致
    pdfFile.getName(),
    requestFile
);

// 4. 发起请求
Call<I3ClaimsResponse> call = yourRetrofitInstance.postDocument(
    "请求目标URL",
    "Bearer 你的授权Token",
    filePart
);

call.enqueue(new Callback<I3ClaimsResponse>() {
    @Override
    public void onResponse(Call<I3ClaimsResponse> call, Response<I3ClaimsResponse> response) {
        // 处理成功响应逻辑
    }

    @Override
    public void onFailure(Call<I3ClaimsResponse> call, Throwable t) {
        // 处理请求失败逻辑
    }
});

额外注意事项

  • 如果需要同时传递其他文本表单参数,可以在接口中添加@Part参数,比如:
    @Multipart
    @POST
    Call<I3ClaimsResponse> postDocument(
        @Url String url,
        @Header("Authorization") String token,
        @Part MultipartBody.Part file,
        @Part("document_title") RequestBody title
    );
    
    对应的参数构建代码:
    RequestBody title = RequestBody.create("报销凭证", MediaType.parse("text/plain"));
    
  • 确认服务端接收的文件字段名确实是files,如果是其他名称(比如file),要同步修改createFormData的第一个参数。

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

火山引擎 最新活动