Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload an image using Google Volley

I would need to upload an image from the application, that I'm developing, to the server and I would like to know how I can develop the Multipart Request to load the image using Google Volley.

Thanks

like image 248
BigNick Avatar asked Apr 03 '15 10:04

BigNick


People also ask

How do you post data on volleyball?

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language. Below is the dependency for Volley which we will be using to get the data from API. For adding this dependency navigate to the app > Gradle Scripts > build.


2 Answers

I have an example to upload images by Google Volley. Take a look:

package net.colaborativa.exampleapp.api;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;

public class PhotoMultipartRequest<T> extends Request<T> {


private static final String FILE_PART_NAME = "file";

private MultipartEntityBuilder mBuilder = MultipartEntityBuilder.create();
private final Response.Listener<T> mListener;
private final File mImageFile;
protected Map<String, String> headers;

public PhotoMultipartRequest(String url, ErrorListener errorListener, Listener<T> listener, File imageFile){
    super(Method.POST, url, errorListener);

    mListener = listener;
    mImageFile = imageFile;

    buildMultipartEntity();
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> headers = super.getHeaders();

    if (headers == null
            || headers.equals(Collections.emptyMap())) {
        headers = new HashMap<String, String>();
    }

    headers.put("Accept", "application/json");

    return headers;
}

private void buildMultipartEntity(){
    mBuilder.addBinaryBody(FILE_PART_NAME, mImageFile, ContentType.create("image/jpeg"), mImageFile.getName());
    mBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    mBuilder.setLaxMode().setBoundary("xx").setCharset(Charset.forName("UTF-8"));
}

@Override
public String getBodyContentType(){
    String contentTypeHeader = mBuilder.build().getContentType().getValue();
    return contentTypeHeader;
}

@Override
public byte[] getBody() throws AuthFailureError{
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        mBuilder.build().writeTo(bos);
    } catch (IOException e) {
        VolleyLog.e("IOException writing to ByteArrayOutputStream bos, building the multipart request.");
    }

    return bos.toByteArray();
}

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    T result = null;
    return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
}

@Override
protected void deliverResponse(T response) {
    mListener.onResponse(response);
}
}

And you can use it like this:

RequestQueue mQueue = Volley.newRequestQueue(context);
PhotoMultipartRequest imageUploadReq = new PhotoMultipartRequest(url, ErrorListener, Listener, imageFile);
mQueue.add(imageUploadReq);

I hope these codes will inspire you.

like image 77
SilentKnight Avatar answered Sep 29 '22 22:09

SilentKnight


@silverknight's answer works, however, I also had to add the following in build.gradle to resolve httpcomponents dependencies:

android {

    ...

    // have to exclude these otherwise you'll get:
    // Error:Gradle: Execution failed for task: ... com.android.builder.packaging.DuplicateFileException: ...
    packagingOptions {
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
    }
}    

dependencies {

    ...

    compile 'com.android.volley:volley:1.0.0'
    compile('org.apache.httpcomponents:httpmime:4.3.6') {
        exclude module: 'httpclient'
    }
    compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'
}

NOTE: Don't use org.apache.httpcomponents:httpclient

You should avoid using the standard version of 'org.apache.httpcomponents:httpclient:4.5.2'

If you try:

android {

    ...

}

dependencies {

    ...

    compile 'com.android.volley:volley:1.0.0'
    compile 'org.apache.httpcomponents:httpcore:4.4.4'
    compile 'org.apache.httpcomponents:httpmime:4.5.2'
    compile('org.apache.httpcomponents:httpclient:4.5.2'
}

you will get:

java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/message/BasicHeaderValueFormatter; in class Lorg/apache/http/message/BasicHeaderValueFormatter; or its superclasses (declaration of 'org.apache.http.message.BasicHeaderValueFormatter' appears in /system/framework/ext.jar)

or something similar to the existing comments [1] [2] [3].

You should rather use the Android port of httpclient, as per this SO answer

NOTE: Use org.apache.httpcomponents:httpmime:4.3.6

You have to use org.apache.httpcomponents:httpmime:4.3.6, you cannot go above version 4.3.x. For example, you may be tempted to use the latest version of httpmime, which at the time of writing is 4.5.2:

android {

    ...

}

dependencies {

    ...

    compile('org.apache.httpcomponents:httpmime:4.5.2') {
        exclude module: 'httpclient'
    }
    compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'

with this config, you will get the following when you invoke PhotoMultipartRequest:

java.lang.NoSuchMethodError: No static method create(Ljava/lang/String;[Lorg/apache/http/NameValuePair;)Lorg/apache/http/entity/ContentType; in class Lorg/apache/http/entity/ContentType; or its super classes (declaration of 'org.apache.http.entity.ContentType' appears in /xxx/base.apk)
like image 23
Donovan Muller Avatar answered Sep 29 '22 22:09

Donovan Muller