Android使用Retrofit和RxJava发送含嵌套自定义类图片的请求
用Retrofit发送嵌套数据类中的图片到服务器
1. 调整数据类字段类型
先把LawyerModel中存储图片的字段类型从Any改为File(单张图片)和Array<File>(多张证书),确保能直接处理图片文件:
data class LawRegRequest( @SerializedName("email") var email: String, @SerializedName("first_name") var first_name: String, @SerializedName("last_name") var last_name: String, @SerializedName("phone") var phone: String, @SerializedName("password") var password: String, @SerializedName("password2") var password2: String, @SerializedName("lawyer") var lawyer: LawyerModel ) data class LawyerModel( @SerializedName("father_name") var father_name: String, @SerializedName("gender") var gender: String, @SerializedName("birth_date") var birth_date: String, @SerializedName("university") var university: String, @SerializedName("service_languages") var service_languages: Array<Int>, @SerializedName("service_types") var service_types: Array<Int>, @SerializedName("voen") var voen: String, @SerializedName("law_practise") var law_practise: String, @SerializedName("lawyer_practise") var lawyer_practice: String, @SerializedName("lawyer_card") var lawyer_card: File, // 修改为File类型 @SerializedName("certificates") var certificates: Array<File> // 修改为File数组 )
2. 定义Retrofit接口
因为要同时发送表单数据和文件,必须使用@Multipart注解构建请求,接口方法如下:
interface ApiService { @Multipart @POST("你的注册接口路径") suspend fun registerLawyer( @PartMap formData: Map<String, RequestBody>, @Part lawyerCard: MultipartBody.Part, @Part certificates: List<MultipartBody.Part> ): Response<你的响应数据类> }
3. 构建请求体并发起请求
手动将嵌套数据类的字段映射为表单参数,同时将图片文件转换为MultipartBody.Part:
// 假设已创建LawRegRequest实例 val request = LawRegRequest(...) // 构建表单数据Map,包含所有文本字段 val formData = mutableMapOf<String, RequestBody>() // 添加顶级字段 formData["email"] = request.email.toRequestBody("text/plain".toMediaType()) formData["first_name"] = request.first_name.toRequestBody("text/plain".toMediaType()) formData["last_name"] = request.last_name.toRequestBody("text/plain".toMediaType()) formData["phone"] = request.phone.toRequestBody("text/plain".toMediaType()) formData["password"] = request.password.toRequestBody("text/plain".toMediaType()) formData["password2"] = request.password2.toRequestBody("text/plain".toMediaType()) // 添加LawyerModel的嵌套字段,格式为"lawyer[字段名]" val lawyer = request.lawyer formData["lawyer[father_name]"] = lawyer.father_name.toRequestBody("text/plain".toMediaType()) formData["lawyer[gender]"] = lawyer.gender.toRequestBody("text/plain".toMediaType()) formData["lawyer[birth_date]"] = lawyer.birth_date.toRequestBody("text/plain".toMediaType()) formData["lawyer[university]"] = lawyer.university.toRequestBody("text/plain".toMediaType()) formData["lawyer[voen]"] = lawyer.voen.toRequestBody("text/plain".toMediaType()) formData["lawyer[law_practise]"] = lawyer.law_practise.toRequestBody("text/plain".toMediaType()) formData["lawyer[lawyer_practise]"] = lawyer.lawyer_practice.toRequestBody("text/plain".toMediaType()) // 处理数组类型字段,格式为"lawyer[数组字段名][]" lawyer.service_languages.forEach { formData["lawyer[service_languages][]"] = it.toString().toRequestBody("text/plain".toMediaType()) } lawyer.service_types.forEach { formData["lawyer[service_types][]"] = it.toString().toRequestBody("text/plain".toMediaType()) } // 处理律师证图片 val lawyerCardFile = lawyer.lawyer_card val lawyerCardRequestBody = lawyerCardFile.asRequestBody("image/jpeg".toMediaType()) // 根据实际图片类型调整 val lawyerCardPart = MultipartBody.Part.createFormData( "lawyer[lawyer_card]", lawyerCardFile.name, lawyerCardRequestBody ) // 处理证书图片数组 val certificateParts = mutableListOf<MultipartBody.Part>() lawyer.certificates.forEach { file -> val certRequestBody = file.asRequestBody("image/jpeg".toMediaType()) val part = MultipartBody.Part.createFormData( "lawyer[certificates][]", file.name, certRequestBody ) certificateParts.add(part) } // 初始化Retrofit并发起请求 val apiService = Retrofit.Builder() .baseUrl("你的服务器基础地址") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) val response = apiService.registerLawyer(formData, lawyerCardPart, certificateParts)
注意事项
- 表单字段的命名格式(如
lawyer[father_name])需要和后端服务器的参数解析规则一致,提前和后端开发确认。 - 图片的MediaType要匹配实际文件类型,比如PNG用
image/png,通用图片类型可以用image/*。 - Android 13及以上版本需要申请
READ_MEDIA_IMAGES权限来读取相册中的图片,低版本需要READ_EXTERNAL_STORAGE权限。
内容的提问来源于stack exchange,提问作者Sirac Seyidov
相关产品推荐
相关产品推荐

