Android中如何使用Retrofit2发送含文件的DTO列表?
解决方案:Retrofit2 上传含文本与图片的对象列表(multipart/form-data)
核心思路
Retrofit 默认不支持直接将自定义数据类的 List 作为 @Part 参数传递,需要手动构造每个列表项对应的 MultipartBody.Part,并按照服务器期望的命名规则(如 dataList[0].text)设置参数名,让服务器能正确解析为对象列表。
1. 定义 Retrofit 服务接口
将接口参数改为接收 List<MultipartBody.Part>,因为我们要手动构造所有上传的部件:
interface PostService { @Multipart @POST("/post") fun addPost( @Part parts: List<MultipartBody.Part> ): Call<PostResponse> }
2. 编写参数转换工具方法
实现一个函数,将你的 List<DataItem> 转换成符合要求的 List<MultipartBody.Part>,关键是给每个部件设置正确的参数名:
fun convertDataItemsToParts(dataItems: List<DataItem>): List<MultipartBody.Part> { val parts = mutableListOf<MultipartBody.Part>() dataItems.forEachIndexed { index, item -> // 构造文本字段的 Part,参数名对应 dataList[$index].text val textRequestBody = RequestBody.create("text/plain".toMediaType(), item.text) val textPart = MultipartBody.Part.createFormData( name = "dataList[$index][text]", value = item.text, body = textRequestBody ) parts.add(textPart) // 构造图片文件的 Part,参数名对应 dataList[$index].image val imageRequestBody = RequestBody.create("image/*".toMediaType(), item.image) val imagePart = MultipartBody.Part.createFormData( name = "dataList[$index][image]", filename = item.image.name, body = imageRequestBody ) parts.add(imagePart) } return parts }
注意:
"image/*"可以根据实际图片类型更改为具体的 MIME 类型(如"image/jpeg"),匹配服务器的接收要求。
3. 调用示例
在业务代码中,将数据列表转换为部件列表后发起请求:
// 假设已有 dataItems: List<DataItem> val parts = convertDataItemsToParts(dataItems) val retrofit = Retrofit.Builder() .baseUrl("你的服务器基础地址") .addConverterFactory(GsonConverterFactory.create()) .build() val service = retrofit.create(PostService::class.java) val call = service.addPost(parts) call.enqueue(object : Callback<PostResponse> { override fun onResponse(call: Call<PostResponse>, response: Response<PostResponse>) { // 处理成功响应 } override fun onFailure(call: Call<PostResponse>, t: Throwable) { // 处理失败情况 } })
为什么之前的方法无效?
- 直接使用
@Part dataList: List<DataItem>:Retrofit 无法自动将自定义数据类拆解为 multipart 所需的独立部件,也无法生成服务器期望的参数命名格式。 - 修改为
DataItem(RequestBody, MultipartBody.Part):这种结构依然不符合 multipart 表单的参数命名规则,服务器无法识别为列表中的对象字段。
内容的提问来源于stack exchange,提问作者blonded
相关产品推荐
相关产品推荐

