Solution Given below
I am using volley library to upload image. Condition is I require to send
- key1 = String value
- key2 = String value
- key3{=file} = Image value i.e. jpeg, jpg
This is the code I am using (commented portion is something I have already tried) -
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import <APP_CLASS IGNORE THIS>.Config
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.util.CharsetUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created by Jimit Patel on 26/09/15.
*/
public class MyClass extends Request<String> {
private static final String TAG = MyClass.class.getSimpleName();
private static final boolean IS_DEBUG = true;
private static final String FILE_PART_NAME = "file";
private MultipartEntityBuilder multipartEntityBuilder;
private Response.Listener<String> mListener;
private Map<String, String> mRequestParams;
private File file;
private String tokenId;
public AddWardrobeRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener,
File file, Map<String, String> requestParams, String tokenId) {
super(method, url, errorListener);
mListener = listener;
this.file = file;
this.tokenId = tokenId;
mRequestParams = requestParams;
buildMultipartEntity();
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
return Response.success("Result", getCacheEntry());
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null
|| headers.equals(Collections.emptyMap())) {
headers = new HashMap<>();
}
headers.put(Config.HEADER_AUTHORIZATION, "Bearer " + tokenId);
// headers.put("Accept", "application/json");
// headers.put("Content-Type", "multipart/form-data");
return headers;
}
@Override
public String getBodyContentType() {
String contentTypeHeader = multipartEntityBuilder.build().getContentType().getValue();
return contentTypeHeader;
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
multipartEntityBuilder.build().writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream bos, building the multipart request.");
}
return bos.toByteArray();
}
private void buildMultipartEntity() {
multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// multipartEntityBuilder.setLaxMode().setBoundary("xx").setCharset(Charset.forName("UTF-8"));
// try {
// multipartEntityBuilder.setCharset(CharsetUtils.get("UTF-8"));
// } catch (UnsupportedEncodingException e) {
// e.printStackTrace();
// }
multipartEntityBuilder.addPart(FILE_PART_NAME, new FileBody(file) );
Set<String> keys = mRequestParams.keySet();
for (String key : keys)
multipartEntityBuilder.addTextBody(key, mRequestParams.get(key));
}
}
Below is the error which I am facing.
Process: com.stylabs.APP.app, PID: 12804
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)
at org.apache.http.entity.ContentType.toString(ContentType.java:153)
at org.apache.http.entity.mime.MultipartFormEntity.<init>(MultipartFormEntity.java:53)
at org.apache.http.entity.mime.MultipartEntityBuilder.buildEntity(MultipartEntityBuilder.java:236)
at org.apache.http.entity.mime.MultipartEntityBuilder.build(MultipartEntityBuilder.java:240)
at MyClass.getBody(MyClass.java:90)
at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:253)
at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:227)
at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:107)
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
Please help me out. Thank you in advance!!
SOLUTION
Although as marked as duplicate I didn't found any solution over there. I finally cracked out what I was missing. I re-read the document over android which I can find it over here - http://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client
So I have removed all those httpcomponents which includes httpcore, httpmime, httpclient, etc.
Don't know now which all crap stuffs were suggested all over stack overflow, all were right maybe till yesterday but not with M preview+. Instead of that add
android {
useLibrary 'org.apache.http.legacy'
}
And the request class which has been used earlier is changed as given below -
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import <APP_CLASS IGNORE THIS>.Config
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created by Jimit Patel on 26/09/15.
*/
public class MyClass extends Request<String> {
private static final String TAG = AddWardrobeRequest.class.getSimpleName();
private static final boolean IS_DEBUG = true;
// This is the key for the file to be sent
private static final String FILE_PART_NAME = "file";
private Response.Listener<String> mListener;
private Response.ErrorListener mErrorListener;
private Map<String, String> mRequestParams;
private File file;
private String tokenId;
private final String BOUNDARY = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f";
private final String CRLF = "\r\n";
private final int MAX_BUFFER_SIZE = 1024 * 1024;
public MyClass(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener,
File file, Map<String, String> requestParams, String tokenId) {
super(method, url, errorListener);
mListener = listener;
mErrorListener = errorListener;
this.file = file;
this.tokenId = tokenId;
mRequestParams = requestParams
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
return Response.success(new String(response.data), getCacheEntry());
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null
|| headers.equals(Collections.emptyMap())) {
headers = new HashMap<>();
}
headers.put(Config.HEADER_AUTHORIZATION, "Bearer " + tokenId);
headers.put("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
return headers;
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
try {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos, "UTF-8"));
Set<String> keys = mRequestParams.keySet();
pw.append(CRLF);
for (String key : keys) {
pw.append("--" + BOUNDARY + CRLF);
pw.append("Content-Disposition: form-data; ");
pw.append("name=\"" + key + "\"" + CRLF + CRLF + mRequestParams.get(key) + CRLF);
}
pw.append("--" + BOUNDARY + CRLF);
pw.append("Content-Disposition: form-data; ");
pw.append("name=\"" + FILE_PART_NAME + "\"; filename=\"" + file.getName() + "\"" + CRLF + CRLF);
dos.writeBytes(pw.toString());
pw.flush();
FileInputStream inputStream = new FileInputStream(file);
int bytesAvailable = inputStream.available();
int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1)
dos.write(buffer, 0, bytesRead);
dos.writeBytes(CRLF + "--" + BOUNDARY + "--" + CRLF);
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
}
And finally got the proper response as desired. I hope this will help others out who all are in trouble same as me. :)