如何将文件列表作为 Retrofit 2 正文的一部分与 Android 中的其他常规字符串字段一起发送?

How to send list of files as part of a Retrofit 2 body alongside other regular string fields in Android?

如问题所述,我需要在 http POST 请求中发送文件列表(在我的例子中是图像),但旁边还有其他字段(常规字符串)。 post 看起来像这样(作为表单数据):

type: customerQuery
user: userId
message: The customer query etc.
contact_number: 01234564789
contact_email: email@address.com
files[]: list of files, as binary

当我只发送文件时,文件上传工作正常,如下:

  @Multipart
  @POST("/exampleendpoint/{id}")
  suspend fun uploadDocument(
      @Path("id") id: String,
      @Part document: MultipartBody.Part
  ): Response<Unit>

如何构造改造 interface/service 以包含文件列表以及其他字段?

谢谢

去做

@Multipart
@POST("exampleendpoint/{id}")
Call<Unit> uploadDocument(@Path("id") String id,
                          @Part("type") RequestBody type,
                          @Part("user") RequestBody user,
                          @Part("message") RequestBody message,
                          @Part("contact_number") RequestBody contact_number,
                          @Part("contact_email") RequestBody contact_email,
                          @Part List<MultipartBody.Part> file);

并像这样添加文件列表

ArrayList<File> tempFilesList = new ArrayList<>();
ArrayList<MultipartBody.Part> images = new ArrayList<>();
for (int i = 0; i < tempFilesList.size(); i++) {
    images.add(prepareImageFilePart("files" + (i + 1), tempFilesList.get(i).getImage()));
}

@NonNull
private MultipartBody.Part prepareImageFilePart(String partName, File file) {
    RequestBody requestFile =
            RequestBody.create(
                    MediaType.parse("image/jpg"),
                    file
            );
    return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}

您可以像这样创建 RequestBody 个其他字段

RequestBody type = RequestBody.create(MediaType.parse("text/plain"), "your data...");

好的,我想我会为任何使用 Kotlin 的人添加我自己的答案,这也是正确的答案,如果 你需要像其他的一样命名 files/images 的列表表单数据。如果你不需要这个,接受的答案是有效的,但在我的情况下它不起作用,因为它们必须在 files[].

改造服务(只是一个简单的@Body body: RequestBody字段,并删除@Multipart)

@POST("exampleendpoint/{id}")
fun uploadDocuments(@Path("id") id: String, @Body body: RequestBody): Response<Unit>;

然后你需要构建一个完整的RequestBody,包括所有你需要的,例子如下:

val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM).apply {
  addFormDataPart("type", "booking")
  addFormDataPart("user", "username")
  addFormDataPart("message", "message text goes here")
  addFormDataPart("contact_number", "0123456789")
  addFormDataPart("contact_email", "email@address.com")
  // my files are List<ByteArray>, okhttp has a few utility methods like .toRequestBody for various types like below
  files.forEachIndexed { index, bytes ->
     addFormDataPart("files[]", "$index.jpg", bytes.toRequestBody("multipart/form-data".toMediaTypeOrNull(), 0, bytes.size))
  }
}.build()
service.uploadDocuments("uploadId", requestBody)