Android POST Images (Files) to Django Server

Hi Guys,

I was working on an app where we have to send images taken from App to Server (Django). I initially thought it would be starightforward sending images with HTTPUrlConnection.  Later realized that it’s one hell of a job.

One of my friend suggested to check codepath. Its has a very good collection of libraries. After browsing for some time, I decided to use retofit (v2.0.1) and okhttp(v3.2) both developed by Square Inc. people. Below are the gradle imports-

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1'
compile 'com.squareup.okhttp3:okhttp:3.2.0'

I’m little bit impatient now so I’m pasting the code with little explanation. Here’s how you initialize Retrofit object and create and APIInterface –

retrofit = new Retrofit.Builder()
        .baseUrl(AppConfig.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

apiService = retrofit.create(ApiEndpointInterface.class);
public interface ApiEndpointInterface {
 @Multipart
 @POST("postsnaps")
 Call<ResponseBody> postSnapshots(@Part("description") String description, @PartMap Map<String, RequestBody> image);
 }

Below is sample code to send multiple send files (Images in my case) –

File file;
Map<String, RequestBody> imgFiles = new HashMap<String,RequestBody>();
for(String imgName: imgFilePaths.keySet()){
    file = new File(imgFilePaths.get(imgName));
    imgFiles.put("file\"; filename=\""+imgName,RequestBody.create(MEDIA_TYPE_JPG, file));
}

Call<ResponseBody> call = getApiService().postSnapshots("DummyValue", imgFiles);
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        Log.d("PostSnapResponse", response.message());
    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.d("PostSnapResponse", t.getMessage());
    }
});
return null;

There is a small catch here – Actually a small hack was needed to send images properly for Django server to identify files in the request and provide in request.FILES to access (People are building very actively, soon it could be better).  Instead of giving form field name, cleverly, field name along with filename attribute is being given. I took the code from Stack Overflow posts and Github issue page of retofit(luckily I found the issue quick, thanks to Google search, Stack Overflow and contributors of Retrofit)  😛

Below is the server side code-

class SaveSnapshots(APIView):
    def handlefileupload(self, ufiles):
        for ufile in ufiles:
            with open("images/"+ufile.name, 'wb+') as destination:
                for chunk in ufile.chunks():
                    destination.write(chunk)

    def post(self,request, *args, **kwargs):
        self.handlefileupload(request.FILES.getlist('file'))
        return Response({"status":"success"})
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s