I am making an app and i have to upload an image using Volley. I tried to google, but didn't find something similar. How to do a multi-part upload of an image and add parameters like user_id when posting this image using Volley?
Using Retrofit is not an option in my case.
First of all create a file MultipartRequest as follows:
public class MultipartRequest extends Request<String> {
private MultipartEntityBuilder entity = MultipartEntityBuilder.create();
private final Response.Listener<String> mListener;
private final File file;
private final HashMap<String, String> params;
public MultipartRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener, File file, HashMap<String, String> params)
{
super(Method.POST, url, errorListener);
mListener = listener;
this.file = file;
this.params = params;
buildMultipartEntity();
buildMultipartEntity2();
}
private void buildMultipartEntity()
{
entity.addBinaryBody(KEY_IMAGE, file, ContentType.create("image/jpeg"), file.getName());
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.setLaxMode().setBoundary("xx").setCharset(Charset.forName("UTF-8"));
try
{
for ( String key : params.keySet() ) {
entity.addPart(key, new StringBody(params.get(key)));
}
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
#Override
public String getBodyContentType()
{
return entity.build().getContentType().getValue();
}
#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;
}
#Override
public byte[] getBody() throws AuthFailureError
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.build().writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
/**
* copied from Android StringRequest class
*/
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
#Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}}
In your activity just make Multipart Request as follows:
public void uploadImage()
{
try {
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Loading...");
pDialog.show();
HashMap params = new HashMap<String, String>();
params.put(KEY_NAME, name);
MultipartRequest sr = new MultipartRequest( UPLOAD_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if ((pDialog != null) && pDialog.isShowing()) {
pDialog.dismiss();
}
Log.d("file", f + "");
Log.d("", ".......response====" + response.toString());
////////
try {
JSONObject object = new JSONObject(response);
String serverCode = object.getString("code");
if (serverCode.equalsIgnoreCase("0")) {
}
if (serverCode.equalsIgnoreCase("1")) {
try {
if ("1".equals(serverCode)) {
JSONObject object1 = object.getJSONObject("data");
}
}
Using Retrofit 2:
You need to use OkHttp’s RequestBody class and encapsulate your file into a request body (means your userid).
1) create interface
public interface FileUploadService {
#Multipart
#POST("/upload")
Call<String> upload(
#Part("myfile\"; filename=\"image.png\" ") RequestBody file,
#Part("userid") RequestBody userid);
}
2) code in activity:
FileUploadService service =
ServiceGenerator.createService(FileUploadService.class);
String userid = "your_userid";
RequestBody data =
RequestBody.create(MediaType.parse("multipart/form-data"), userid);
File file = new File("path/to/your/file");
RequestBody requestBody =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
Call<String> call = service.upload(requestBody, data);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.v("Upload", "success");
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e("Upload", t.getMessage());
}
});
Refer link: https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server
Related
Hi I am relatively new to android, I have used multipart request to upload an image to server using volley. The image is being uploaded correctly but I am getting the response as null. I checked on postman, I am strangely getting the correct response there.
MultipartRequest.java
public class MultipartRequest extends Request<JSONObject> {
private static final String FILE_PART_NAME = "user[avatar]";
private long cacheTimeToLive = 0;
private MultipartEntityBuilder mBuilder = MultipartEntityBuilder.create();
private final Response.Listener<JSONObject> mListener;
private final File mImageFile;
protected Map<String, String> headers;
public MultipartRequest(String url, File imageFile, Listener<JSONObject> listener, ErrorListener errorListener){
super(Method.PUT, 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<JSONObject> parseNetworkResponse(NetworkResponse response) {
JSONObject result = null;
return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
}
#Override
protected void deliverResponse(JSONObject response) {
mListener.onResponse(response);
}
}
uploadImage method :-
private void uploadImage(final Bitmap bitmap){
String name = "DP_"+ userName +".jpeg";
try {
file=bitmapToFile(name,bitmap);
} catch (IOException e) {
e.printStackTrace();
}
MultipartRequest jsonRequest = new MultipartRequest( UPLOAD_URL,
file,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG,response.toString());
try {
// parseUserPhotoResponse(response);
Picasso.with(getApplicationContext())
.load(destination)
.placeholder(R.mipmap.placeholder)
.resize(avatarSize, avatarSize)
.centerCrop()
.transform(new CircleTransformation())
.into(ivUserProfilePhoto);
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.d(TAG, "Error: " + volleyError.getMessage());
if(volleyError!=null)
{
try {
NetworkResponse networkResponse = volleyError.networkResponse;
if (networkResponse != null) {
String responseBody = new String(volleyError.networkResponse.data, "utf-8");
JSONObject jsonObject = new JSONObject(responseBody);
Log.d(TAG, "Response body" + responseBody.toString());
Log.d(TAG, jsonObject.toString());
if (jsonObject.getBoolean("error") == false) {
} else {
Toast.makeText(getApplicationContext(), "" + jsonObject.getString("message"), Toast.LENGTH_LONG).show();
}
}
} catch (JSONException e) {
//Handle a malformed json response
} catch (UnsupportedEncodingException error) {
}
}
}
})
;
//Creating a Request Queue
jsonRequest.setShouldCache(false);
MyApplication.getInstance().addToRequestQueue(jsonRequest, "UPLOAD_IMAGE");
}
I am sending multipart Post request in Volley along with the JSon params {as required by server } , but at server side null params are received .
In this request, I need to send Requested params in one part fist, and the image file in the next part .
Map<String, String> params = new HashMap<String, String>();
params.put("appkey", Constants.REQUEST_API_KEY);
params.put("LoginID",issueRequest.getUserName());
params.put("device_id", issueRequest.getImei().toString());
params.put("tokenID", AppSharedPreferance.getAppSharedPreferanceInstance(mContext).getToken(Constants.REQUEST_TOKEN, null));
params.put("issueId", String.valueOf(mRequestIssueId));
params.put("serverID", String.valueOf(mServerId));
JSONObject requestObj = new JSONObject();
requestObj.put("ISSUE_DATA_KEY", new JSONObject(params));
I am requesting like :
PhotoMultipartRequest<JSONObject> photoMultipartRequest=null;
photoMultipartRequest=new PhotoMultipartRequest<JSONObject>(url, requestObj.toString(), new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(IssueRequest.TAG, "inside Error");
VolleyLog.d(Constants.REQUEST_ERROR, "Error had occured " + error.getCause());
}
}, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.v(IssueRequest.TAG,"Responce -> Issue Attachments "+response);
String status = null;
int code=-1;
try {
code = (int) response.getInt("error_code");
status = response.getString("response_string");
} catch (JSONException e) {
e.printStackTrace();
}
Log.v(IssueRequest.TAG, "code->" + code + "status->" + status + "Responce ->" + response.toString());
}
},
new File(issue.getAttachmentPath().toString()));
photoMultipartRequest.setRetryPolicy(new RetryPolicyClass());
Log.v(TAG, "Issue data " + photoMultipartRequest.toString());
AppController.getInstance().addToRequestQueue(photoMultipartRequest);
When i am printing the response object, it has null params .
{"response_string":"Invalid request.","error_code":"1","required_params":null}
My VolleyRequest Class :
public class PhotoMultipartRequest<T> extends Request<T> {
private static final String FILE_PART_NAME = "file";
private static final String FILE_JSON_PART_NAME = "parms";
private MultipartEntityBuilder mBuilder = MultipartEntityBuilder.create();
private final Response.Listener<T> mListener;
private final File mImageFile;
protected Map<String, String> headers;
protected String params;
protected static final String PROTOCOL_CHARSET = "utf-8";
public PhotoMultipartRequest(String url, ErrorListener errorListener, Listener<T> listener, File imageFile){
super(Method.POST, url, errorListener);
mListener = listener;
mImageFile = imageFile;
buildMultipartEntity();
}
public PhotoMultipartRequest(String url,String params, ErrorListener errorListener, Listener<T> listener, File imageFile){
super(Method.POST, url, errorListener);
mListener = listener;
mImageFile = imageFile;
this.params=params;
try {
buildMultipartEntity1();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
#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 buildMultipartEntity1() throws UnsupportedEncodingException {
mBuilder.addPart(FILE_JSON_PART_NAME, new StringBody(params));
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"));
}
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)
{
try {
String result = null;
result = new String( response.data, HttpHeaderParser.parseCharset( response.headers ) );
return ( Response<T> ) Response.success( new JSONObject( result ), HttpHeaderParser.parseCacheHeaders(response) );
} catch ( UnsupportedEncodingException e ) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
#Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
}
I cannot find any clue of what went wrong. So, can anyone help me to correct my request class?
I am trying to upload an image using Volley library in android but no data is being send to the server side as the file is created but it does not contain any data.
public class ProfilePicSendReq extends Request<String>
{
private MultipartEntityBuilder mBuilder = MultipartEntityBuilder.create();
private final Response.Listener<String> mListener;
private final File mImageFile;
protected Map<String, String> headers;
Context context;
public ProfilePicSendReq(Context cntxt, String url, Listener<String> listener, ErrorListener errorListener, File imageFile)
{
super(Method.POST, url, errorListener);
mListener = listener;
mImageFile = imageFile;
buildMultipartEntity();
context = cntxt;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
headers = super.getHeaders();
if (headers == null
|| headers.equals(Collections.emptyMap()))
{
headers = new HashMap<String, String>();
}
headers.put("Accept", "text/plain");
return headers;
}
private void buildMultipartEntity()
{
mBuilder.addBinaryBody(mImageFile.getName(), mImageFile, ContentType.create("image/jpeg"), "profilePic");
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) {
Log.d("PicUploadMsg : ", "IOException writing to ByteArrayOutputStream bos, building the multipart request.");
}
return bos.toByteArray();
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
String result = new String(response.data);
return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
}
#Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
}
It is the famous sending Mulipart data using volley i have tried several time but no data appears to leave from the client side.
I want to upload files(images,documents etc) from my android application to my server.I'm using Volley library for network calls in my application.
I'm using the following code to upload files but it is not performing any operation.(showing volley timeout error finally)
public class MultipartRequest extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private final Response.Listener<String> mListener;
private final File mFilePart;
private String mStringPart,accessToken;
public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file,String accessToken)
{
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
this.accessToken = accessToken;
buildMultipartEntity();
}
private void buildMultipartEntity()
{
entity.addPart(FILE_PART_NAME, new FileBody(mFilePart));
try
{
entity.addPart("Content-Disposition", new StringBody("form-data"));
entity.addPart("dir_path", new StringBody("IzEzOjE3"));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
#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("Content-Type", "multipart/form-data");
headers.put("_pkta",accessToken);
return headers;
}
#Override
public String getBodyContentType()
{
return entity.getContentType().getValue();
}
#Override
public byte[] getBody() throws AuthFailureError
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
#Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
}
please help me on how to implement file upload in android(either by volley or any other)
Try
public MultiPartRequest(String url, String filePath, Response.Listener<String> listener, Response.ErrorListener errorListener)
{
super(Method.POST, url, errorListener);
entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
file = new File(filePath);
mListener = listener;
buildMultipartEntity();
}
also, in my case I didn't override getHeaders, just passed other values with addPart, e.g:
entity.addPart("file", new FileBody(file, "image/jpeg")); // for image
entity.addPart("id", new StringBody(userid));
hope this helps.
I am trying to use DWorkS/VolleyPlus to make a MultiPartRequest.
I have searched through the GitHub repository, and it's sample code, but I can find no examples using this class.
I am getting a 411 response code when I make my request. My understanding is that this is sent by the server as a response when it refuses to accept a message without a content-length header. How would I go about providing this?
Below is the relevant part of the LogCat showing the error, and my method.
Looking at the code for MultiPartRequest, it has a field called isFixedStreamingMode. This name sounds similar to setFixedLengthStreamingMode for a connection, however I can't see where it ever gets used in the code. Also it is a boolean not an int, so I cannot supply a length with it. Does anyone know what this field is for?
Has anyone successfully used MultiPartRequest from this library? Any advice or examples would be greatly appreciated.
I am currently successfully making POST, GET and PUT methods using the StringRequest class from this library.
LogCat
03-11 22:17:15.388 25236-25236/au.com.xxx.yyy D/MainActivity﹕ postMyItem: http://yyy.zzz.com.au/api/v1/my_item
03-11 22:17:15.507 25236-25309/au.com.xxx.yyy E/Volley﹕ [5861] BasicNetwork.performRequest: Unexpected response code 411 for http://yyy.zzz.com.au/api/v1/my_item
03-11 22:17:15.508 25236-25236/au.com.xxx.yyy D/MainActivity﹕ error response: <html>
<head><title>411 Length Required</title></head>
<body bgcolor="white">
<center><h1>411 Length Required</h1></center>
<hr><center>nginx/1.1.19</center>
</body>
</html>
03-11 22:17:15.508 25236-25236/au.com.xxx.yyy D/MainActivity﹕ Volley Error: com.android.volley.error.VolleyError
Method
public void postMyItem(final MyItem myItem) {
String url = getString(R.string.url__server_api) + getString(R.string.post__my_item);
MultiPartRequest request = new MultiPartRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Volley POST MyItem response: " + response);
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Volley Error: " + error);
try {
String response = new String(error.networkResponse.data, "utf-8");
Log.d(TAG, "error response: " + response);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
})
{
#Override
protected Response parseNetworkResponse(NetworkResponse networkResponse) {
return null;
}
#Override
public Map<String, String> getHeaders() throws com.android.volley.error.AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put(getString(R.string.header_field__access_token), mAccess_token);
return map;
}
};
if (myItem.name != null) {
request.addMultipartParam("name", "multipart/mixed", myItem.name);
}
if (myItem.quantity != null) {
request.addMultipartParam("quantity", "multipart/mixed", myItem.quantity);
}
...
//TODO: request.addFile(name, filePath)
VolleySingleton.getInstance(this).addToRequestQueue(request);
}
So sometime the servers might require content length to be told before uploading imagesetFixedStreamingMode is the method. The sample code is below
SimpleMultipartRequest request = new SimpleMultipartRequest(Method.POST, apiUrl, mListener, mErrorListener);
request.addFile("photo", image_path);
RequestQueue mRequestQueue = Volley.newRequestQueue(getApplicationContext());
mRequestQueue.add(request);
mRequestQueue.setFixedStreamingMode(true);
mRequestQueue.start();
You can use MultipartEntitiy in volley request for adding multipart data in your request body, by overriding getBody method like this:
public class MultipartRequest extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private static final String STRING_PART_NAME = "text";
private static final String SELFIE_IMAGE = "selfieImage";
private static final String SELFIE_CAPTION = "cap";
private final Response.Listener<String> mListener;
private final File mFilePart;
private final String mStringPart;
public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file, String stringPart)
{
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
mStringPart = stringPart;
buildMultipartEntity();
}
private void buildMultipartEntity()
{ System.out.println("buildMultipartEntity");
entity.addPart(SELFIE_IMAGE, new FileBody(mFilePart));
try
{
entity.addPart(SELFIE_CAPTION, new StringBody(mStringPart));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
#Override
public String getBodyContentType()
{ System.out.println("getBodyContentType");
return entity.getContentType().getValue();
}
#Override
public byte[] getBody() throws AuthFailureError{
System.out.println("getBody");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
#Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
System.out.println("getHeaders");
if (headers == null
|| headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
AppController.getInstance().addSessionCookie(headers);
return headers;
}
}