Uploading Files to an API

Welcome to the next step in your journey of mastering API interactions with Kotlin! In our previous lesson, you learned how to download files efficiently using an API, enhancing your skills in file management. Today, we will take a look at the reverse process: uploading files to an API. This capability is crucial for creating applications that need to store or share files, such as documents, images, or any other type of data with an external server.

Understanding file uploads will further expand your ability to interact with APIs, equipping you to build more robust and feature-complete applications. By the end of this lesson, you will learn how to send a file to a server using Kotlin, ensuring that you can manage uploads confidently and efficiently.

Understanding HTTP File Uploads

To upload files via HTTP, the POST method is commonly used, as it’s designed for submitting data to a server, including files. The key to sending files is using multipart/form-data, a format that allows both text and binary data to be sent together, organized into separate parts. This format ensures the server can properly handle the uploaded file along with any additional data.

In Kotlin, the OkHttp library makes this process seamless. When using OkHttp, you don't need to worry about manually crafting the multipart/form-data. The library takes care of it for you when you provide the file in the right format.

Here's a simple example showing how to upload a file using OkHttp:

Kotlin
1import okhttp3.* 2import java.io.File 3import java.io.IOException 4import okhttp3.MediaType.Companion.toMediaType 5import okhttp3.RequestBody.Companion.asRequestBody 6 7fun uploadFile(filePath: String, url: String) { 8 val client = OkHttpClient() 9 10 // Create a file object for the file to be uploaded 11 val file = File(filePath) 12 13 // Create a request body with the file and the media type 14 val requestBody = MultipartBody.Builder() 15 .setType(MultipartBody.FORM) 16 .addFormDataPart("file", file.name, file.asRequestBody("text/plain".toMediaType())) 17 .build() 18 19 // Build the request 20 val request = Request.Builder() 21 .url(url) 22 .post(requestBody) 23 .build() 24 25 // Execute the request 26 client.newCall(request).execute().use { response -> 27 if (!response.isSuccessful) throw IOException("Unexpected code $response") 28 29 println("File uploaded successfully: ${file.name}") 30 } 31}

In this example, the file is wrapped in a RequestBody with the appropriate media type. The MultipartBody.Builder is used to construct the multipart request, and the OkHttpClient executes the request, making file uploads straightforward and allowing you to focus on the functionality of your application.

Code Example: Uploading a File

Now, let's delve into the process of uploading a file using Kotlin. Consider the following code example, which utilizes the "/notes" endpoint to upload a file named meeting_notes.txt.

Kotlin
1import okhttp3.* 2import java.io.File 3import java.io.IOException 4import okhttp3.MediaType.Companion.toMediaType 5import okhttp3.RequestBody.Companion.asRequestBody 6 7fun main() { 8 val baseUrl = "http://localhost:8000" 9 val fileName = "meeting_notes.txt" 10 11 try { 12 uploadFile(fileName, "$baseUrl/notes") 13 } catch (e: IOException) { 14 println("Error occurred: ${e.message}") 15 } 16} 17 18fun uploadFile(filePath: String, url: String) { 19 val client = OkHttpClient() 20 val file = File(filePath) 21 22 if (!file.exists()) { 23 println("File not found: $filePath") 24 return 25 } 26 27 val requestBody = MultipartBody.Builder() 28 .setType(MultipartBody.FORM) 29 .addFormDataPart("file", file.name, file.asRequestBody("text/plain".toMediaType())) 30 .build() 31 32 val request = Request.Builder() 33 .url(url) 34 .post(requestBody) 35 .build() 36 37 client.newCall(request).execute().use { response -> 38 if (!response.isSuccessful) { 39 val errorMessage = response.body?.string() ?: "Unknown error" 40 println("HTTP error occurred: ${response.code}") 41 println("Error: $errorMessage") 42 } else { 43 println("File uploaded successfully: ${file.name}") 44 } 45 } 46}

This code example demonstrates how to properly upload a file to an API:

  • The File class is used to represent the file to be uploaded.
  • The MultipartBody.Builder constructs the multipart request, attaching the file in the request.
  • If the upload is successful, a success message is printed to the console.

In this example, requests are encapsulated in a try-catch block to gracefully address potential issues. A check is performed to ensure the file exists before attempting to upload. By managing these exceptions, you can ensure your application behaves predictably, even if something goes wrong during file upload.

Verifying the File Upload

Once a file is uploaded, it's important to verify it to ensure that the file is stored correctly on the server. You can achieve this by sending a GET request to the corresponding endpoint and checking the content of the uploaded file.

Kotlin
1fun verifyFileUpload(fileName: String, url: String) { 2 val client = OkHttpClient() 3 4 val request = Request.Builder() 5 .url("$url/$fileName") 6 .get() 7 .build() 8 9 client.newCall(request).execute().use { response -> 10 val responseBody = response.body?.string() 11 if (!response.isSuccessful) { 12 val errorMessage = responseBody ?: "Unknown error" 13 println("HTTP error occurred: ${response.code}") 14 println("Error: $errorMessage") 15 } else { 16 println(responseBody) 17 } 18 } 19}

In this code, we retrieve the content of the file from the server and print it out. This allows us to confirm that the file has been uploaded and stored successfully.

Plain text
1Meeting Notes 2 3Date: 2023-10-18 4Time: 3:00 PM 5Location: Conference Room A 6 7Attendees: 8- Alice Johnson 9- Bob Smith 10- Charlie Brown 11...

This output confirms that the file "meeting_notes.txt" is present on the server and its contents are intact, with details such as the date, time, location, and attendees of a meeting.

Summary and Next Steps

In this lesson, you built upon your previous knowledge of file downloads and learned to upload files to a server using Kotlin's OkHttp library. We explored the steps to set up your environment, the importance of checking file existence, and the method to send POST requests for file uploads. You also learned how robust error handling can lead to more reliable applications.

Now, it's time to get hands-on with the practical exercises following this lesson. Use these exercises as an opportunity to reinforce your understanding and experiment with different file types and sizes. This will not only enhance your skills but also prepare you for advanced API interactions in future lessons. Happy coding, and keep up the excellent work!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal