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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 03:44:54