We've already shown you in a tutorial how to upload files to a server. In this tutorial, we'll show you a special case: uploading multiple files with one request.
If you want to catch up with one of our plenty Retrofit topics, check our outline of posts:
Retrofit Series Overview
- Getting Started and Creating an Android Client
- Basics of API Description
- Creating a Sustainable Android Client
- URL Handling, Resolution and Parsing
- How to Change API Base Url at Runtime
- Multiple Server Environments (Develop, Staging, Production)
- Share OkHttp Client and Converters between Retrofit Instances
- Upgrade Guide from 1.9
- Beyond Android: Retrofit for Java Projects
- How to use OkHttp 3 with Retrofit 1
- Synchronous and Asynchronous Requests
- Send Objects in Request Body
- Add Custom Request Header
- Manage Request Headers in OkHttp Interceptor
- Dynamic Request Headers with @HeaderMap
- Multiple Query Parameters of Same Name
- Optional Query Parameters
- Send Data Form-Urlencoded
- Send Data Form-Urlencoded Using FieldMap
- How to Add Query Parameters to Every Request
- Add Multiple Query Parameter With QueryMap
- How to Use Dynamic Urls for Requests
- Constant, Default and Logic Values for POST and PUT Requests
- Cancel Requests
- Reuse and Analyze Requests
- Optional Path Parameters
- How to Send Plain Text Request Body
- Customize Network Timeouts
- How to Trust Unsafe SSL certificates (Self-signed, Expired)
- Dynamic Endpoint-Dependent Interceptor Actions
- How to Update Objects on the Server (PUT vs. PATCH)
- How to Delete Objects on the Server
- Introduction to (Multiple) Converters
- Adding & Customizing the Gson Converter
- Implementing Custom Converters
- How to Integrate XML Converter
- Access Mapped Objects and Raw Response Payload
- Supporting JSON and XML Responses Concurrently
- Handling of Empty Server Responses with Custom Converter
- Send JSON Requests and Receive XML Responses (or vice versa)
- Unwrapping Envelope Responses with Custom Converter
- Wrapping Requests in Envelope with Custom Converter
- Define a Custom Response Converter
Upload Multiple Files With Retrofit 2
Before going into the details of uploading multiple files, please make sure you understand the principles of uploading files with Retrofit 2. The approach for multiple files is going to be very similar.
First of all, we need to extend our FileUploadService
class for the new upload with multiple files:
public interface FileUploadService {
// previous code for single file uploads
@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(
@Part("description") RequestBody description,
@Part MultipartBody.Part file);
// new code for multiple files
@Multipart
@POST("upload")
Call<ResponseBody> uploadMultipleFiles(
@Part("description") RequestBody description,
@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2);
}
If you compare the two interface methods for uploadFile()
and uploadMultipleFiles()
, you can spot the difference very easily. Retrofit 2 makes it simple to add new file parts. On the side of the interface declaration, we just need to add another line @Part MultipartBody.Part file
. The uploadMultipleFiles()
method currently only supports exactly two files. You need to adjust the amount of MultipartBody.Part
parts to your needs. In a later tutorial we'll look at a way to add a dynamic amount of files to your request.
Declaring the interface is only half of the work. The other part is the implementation in the activity or fragment lifecycle. Since we're working with multiple files now, we've implemented two helper methods to make things more robust:
@NonNull
private RequestBody createPartFromString(String descriptionString) {
return RequestBody.create(
okhttp3.MultipartBody.FORM, descriptionString);
}
@NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
// use the FileUtils to get the actual file by uri
File file = FileUtils.getFile(this, fileUri);
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(
MediaType.parse(getContentResolver().getType(fileUri)),
file
);
// MultipartBody.Part is used to send also the actual file name
return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}
The createPartFromString()
method can be useful for sending descriptions along a multipart upload. The prepareFilePart()
method builds a MultipartBody.Part
object, which contains a file (like a photo or video). The wrapping in a MultipartBody.Part
is necessary to upload files with Retrofit 2.
So let's use our helper methods to send two files:
Uri file1Uri = ... // get it from a file chooser or a camera intent
Uri file2Uri = ... // get it from a file chooser or a camera intent
// create upload service client
FileUploadService service =
ServiceGenerator.createService(FileUploadService.class);
// create part for file (photo, video, ...)
MultipartBody.Part body1 = prepareFilePart("video", file1Uri);
MultipartBody.Part body2 = prepareFilePart("thumbnail", file2Uri);
// add another part within the multipart request
RequestBody description = createPartFromString("hello, this is description speaking");
// finally, execute the request
Call<ResponseBody> call = service.uploadMultipleFiles(description, body1, body2);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
That's all you need to do to send multiple files in one request. Of course, you could add another or many more parts to the interface, if necessary. Using this approach you can send as many files as you wish.
Summary
In this tutorial, you've learned how to upload multiple files. Additionally, we've shown you two helper methods to make file handling easier for you. Retrofit 2 assists you by simplifying the process. If you run into any problems, let us know in the comments!