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
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.
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.
@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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With