I\'m posting content to the server in a multipart/form-data request. and the data I\'m posting contains multiple parameters including a file array parameter (files[]).
I think you should change the MediaType for file. and you also check the link for that https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server and for send file with @Part MultipartBody.Part
MediaType mediaTypeForText = MediaType.parse("text/plain");
MediaType mediaTypeForImage = MediaType.parse("image/*");
Map<String, RequestBody> params = new HashMap<>();
params.put("first-parameter", MultipartBody.create(mediaTypeForText, "first-parameter-value"));
params.put("second-parameter", MultipartBody.create(mediaTypeForText, "second-parameter-value"));
params.put("files[0]", MultipartBody.create(mediaTypeForImage, new File(fileUri.getPath()));
params.put("files[1]", MultipartBody.create(mediaTypeForImage, new File(fileUri.getPath()));
First of all, I've been doing one thing wrong which is using a @PartMap Map<String, RequestBody>
in the ApiDefinitions
interface.
In case you're doing a post request with multiple parameters and multiple files, always make sure when defining the api method to use RequestBody
for non-file parameters, and use MultipartBody.Part
for file parameters.
In my case I needed to send an array of files, so the parameter that has worked for me is MultipartBody.Part[]
.
This is the new api definition :
@Multipart
@POST("*******/new")
Call<ApiResponse> submitNew(@Header("Authorization") String authHeader,
@Part("first-parameter") RequestBody firstParameter,
@Part("first-parameter") RequestBody secondParameter,
@Part MultipartBody.Part[] files);
The second mistake I made was not noticing this:
PostMan Log: Content-Disposition: form-data; name="files[0]"; filename=""
Retrofit Log: Content-Disposition: form-data; name="files[0]"
The filename was not included in the multipart request, which apparently is a known issue when uploading files to a php service !
I didn't make the api, and I don't have any php background so please don't judge me. As far as I know, I was successfully sending files to the service api, but the api didn't know how to save these files !
So when sending the request:
List<Uri> files; //These are the uris for the files to be uploaded
MediaType mediaType = MediaType.parse("");//Based on the Postman logs,it's not specifying Content-Type, this is why I've made this empty content/mediaType
MultipartBody.Part[] fileParts = new MultipartBody.Part[files.size()];
for (int i = 0; i < files.size(); i++) {
File file = new File(files.get(i).getPath());
RequestBody fileBody = RequestBody.create(mediaType, file);
//Setting the file name as an empty string here causes the same issue, which is sending the request successfully without saving the files in the backend, so don't neglect the file name parameter.
fileParts[i] = MultipartBody.Part.createFormData(String.format(Locale.ENGLISH, "files[%d]", i), file.getName(), fileBody);
}
Call<ApiResponse> call = api.submitNew("Auth Token", MultipartBody.create(mediaType, "first_parameter_values"), MultipartBody.create(mediaType, "second_parameter_values"), fileParts);
call.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
}
});