Uploading Files to AWS S3 with Progress - Kotlin

Mehmet Gür
Getir
Published in
2 min readAug 24, 2022

In this post we’ll use Kotlin Coroutines and Retrofit2 to upload files to S3 Bucket on Android. In our case, we get S3 url from our backend server. So this post will be more about the file uploading part.

First, create a function to choose file :

We used registerForFiles.launch(this) to get the result of this intent. So now we need to create an ActivityResultLauncher named registerForFiles:

In the above codes, we got the URI of selected file. We’ll use this URI to create a RequestBody. Why we need to create a RequestBody? Well! Normally files can be uploaded to server as MultipartBody.Part on Android but using MultiPartBody can cause problems as mentioned here.

We will create our own RequestBody because later we’ll add some code to this class to show the progress of the uploading status. Let’s create a RequestBody:

With that class we can get the media type and content length of the file from the file URI. writeTo() function opens an inputStream to the file and it’s used to transmit the file. We’re also using ContentResolver to access and operate on files.

Now we can create a Retrofit function to upload this RequestBody as a file:

That’s it! Now we can call this function in a Fragment and upload files.

Note: In our case that contentType was handling from backend. So I didn’t need to send it to server but it might be required in your case. If it’s, you can get contentType from the file URI.

Now we’re able to send the files to Amazon S3 Bucket. It’s done!!!

If you want you can also add a progressBar to observe uploading status of the file according to uploaded bytes of the file. To do this we need to make some changes in our FileRequestBody class. So let’s do this!

First edit FileRequestBody class like this:

We added a higher-order function as parameter to observe uploading status of the files. writtenBytes represents the uploaded bytes to server and contentLength represents the total file size. Due to writeTo() function runs multiple times we can get proper writtenBytes values.

Transmitting the request body is performed by writing it to a Sink, we will wrap the default sink with our own one that counts the bytes that are transmitted and reports them back via a progress callback. We can wrap the default sink into our new CountingSink and write to a buffered version of that, in order to both transmit the file and observe its progress.

We are able to get written bytes of the file. Now all we have to do is update a progressBar according to this writtenBytes in UI:

Set android:max="100" attr of progressBar in XML. So the progressBar will be updated according to uploading status.

Thanks for reading! :)

--

--

Mehmet Gür
Getir
Writer for

Quality > Quantity && Simplicity > Complexity