This tutorial only discusses Android image upload using multipart with Retrofit2. If you want to learn about sending HTTP requests using Retrofit2 from basics read this.
Why use Multipart to Upload Image ?
Before diving deep into Android Image upload, its important to understand some basics of HTTP requests. Most importantly how are different types of data sent to server. POST requests are used to send data to server, this data can either be simple readable text fields or sometimes even non alphanumeric binary data(like image files). In our last tutorial6 we saw how to send a simple POST request with retrofit. To facilitate sending different types of data we have different methods given below
x-www-urlencoded
multipart/form-data
(spec points to RFC2388)text-plain
. This is “not reliably interpretable by computer”, so it should never be used in production, and we will not look further into it.
With application/x-www-form-urlencoded
, the body of the HTTP message sent to the server is essentially one giant query string — name/value pairs are separated by the ampersand (&
), and names are separated from values by the equals symbol (=
). But for each non-alphanumeric byte that exists in one of our values, it’s going to take three bytes to represent it. This is very inefficient for sending large files hence this method cannot be used for sending image files
That’s where multipart/form-data comes in. Multipart sends a single object(file) in various parts, each part is separated by a boundary and has some portion of object’s data. Each part also has its own headers like Content-Type, Content-Deposition. Below is a sample representation of multipart request to upload two file a.txt and a.html
POST / HTTP/1.1 [[ Less interesting headers ... ]] Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150 Content-Length: 834 -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="text1" text default -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="text2" aωb -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file1"; filename="a.txt" Content-Type: text/plain Content of a.txt. -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file2"; filename="a.html" Content-Type: text/html <!DOCTYPE html><title>Content of a.html.</title> -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file3"; filename="binary" Content-Type: application/octet-stream aωb -----------------------------735323031399963166993862150--
This efficiency of sending single file in multiple parts is the reason most of the browsers use Multipart to upload files. Retrofit is one of the few network libraries which has built in support for Multipart. This enables you to upload any files from your app without worrying of any of the internal details of Multipart.
Android Image Upload
In the following example we will be uploading a Image file to Server using Multipart with Retrofit2. As per the scope of this example we will only cover how to upload a image/file on server but if you want to first learn how to pick image from gallery/camera please read this example
Step 1 : Add Gradle dependencies
implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
Step 2 : Create Retrofit Instance
Create a class NetworkClient.java to retrieve the Retrofit object anywhere in your application. This instance will be used to send the HTTP request from your app.
public class NetworkClient { private static final String BASE_URL = ""; private static Retrofit retrofit; public static Retrofit getRetrofitClient(Context context) { if (retrofit == null) { OkHttpClient okHttpClient = new OkHttpClient.Builder() .build(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } }
Step 3 : Define the Upload API
We know that with Retrofit2, interface methods are used to define the APIs with which the app will be interacting. Therefore for uploading an image we define the following API. Note the use of @Multipart and @Part
ublic interface UploadAPIs { @Multipart @POST("/upload") Call<ResponseBody> uploadImage(@Part MultipartBody.Part file, @Part("name") RequestBody requestBody); }
@Multipart
Denotes that the request body is multi-part. Parts should be declared as parameters and annotated with @Part
.
@Part
This denotes a single part of Multipart request. The parameter on which this type exists will be processed in three ways
- If the parameter type is
MultipartBody.Part
the contents will be used directly. Part name is not required with the annotation (i.e.,@Part MultipartBody.Part part
). - If the parameter type is
RequestBody
the value will be used directly with its content type. Supply the part name in the annotation (e.g.,@Part("foo") RequestBody foo
). - Other object types will be converted to an appropriate representation by using a converter. Supply the part name in the annotation (e.g.,
@Part("foo") Image photo
).
Step 4 : Uploading an Image
Now comes most important part- Uploading a File. Input parameter to this method is a simple image file path. As already mentioned if you want to learn how to get file path of the images from gallery/camera read this tutorial
- Using the file path we create a file object and then create a request body with that image file. Now with the request body we create a MultipartBody.Part by passing file name and part name as shown in the snippet below. This MultipartBody.Part is sent to Retrofit to initiate image upload
- We can even send some text fields along with the image. Make sure server is able to handle all tha parts that you are sending. Since this is a demo example I am just sending a sample description text request body along with the image.
- Both the text and image are sent as parts along with the mutipart requests
private void uploadToServer(String filePath) { Retrofit retrofit = NetworkClient.getRetrofitClient(this); UploadAPIs uploadAPIs = retrofit.create(UploadAPIs.class); //Create a file object using file path File file = new File(filePath); // Create a request body with file and image media type RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file); // Create MultipartBody.Part using file request-body,file name and part name MultipartBody.Part part = MultipartBody.Part.createFormData("upload", file.getName(), fileReqBody); //Create request body with text description and text media type RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "image-type"); // Call call = uploadAPIs.uploadImage(part, description); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { } @Override public void onFailure(Call call, Throwable t) { } }); }
Conclusion
This finishes our fully functional Android Image Upload Example, but in software development just getting something working is not enough. One of the major characteristic of a good programmer is that he writes clean code. And the best tips and guidelines for clean code are mentioned in this book by noted software expert Robert C. Martin. It is a must read for every software engineer.
If you are new to Android you should definitely go through the list of Android examples here. It is a must read for every Android Developer
sexy Indian girls