-
-
Save AizazZaidee/55c316152ecace931bc0 to your computer and use it in GitHub Desktop.
package com.az.custom.request; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.FilterOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.io.UnsupportedEncodingException; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.apache.http.HttpEntity; | |
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 com.android.volley.AuthFailureError; | |
import com.android.volley.NetworkResponse; | |
import com.android.volley.Request; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyLog; | |
import com.beusoft.app.AppContext; | |
public class MultipartRequest extends Request<String> { | |
MultipartEntityBuilder entity = MultipartEntityBuilder.create(); | |
HttpEntity httpentity; | |
private String FILE_PART_NAME = "files"; | |
private final Response.Listener<String> mListener; | |
private final File mFilePart; | |
private final Map<String, String> mStringPart; | |
private Map<String, String> headerParams; | |
private final MultipartProgressListener multipartProgressListener; | |
private long fileLength = 0L; | |
public MultipartRequest(String url, Response.ErrorListener errorListener, | |
Response.Listener<String> listener, File file, long fileLength, | |
Map<String, String> mStringPart, | |
final Map<String, String> headerParams, String partName, | |
MultipartProgressListener progLitener) { | |
super(Method.POST, url, errorListener); | |
this.mListener = listener; | |
this.mFilePart = file; | |
this.fileLength = fileLength; | |
this.mStringPart = mStringPart; | |
this.headerParams = headerParams; | |
this.FILE_PART_NAME = partName; | |
this.multipartProgressListener = progLitener; | |
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); | |
try { | |
entity.setCharset(CharsetUtils.get("UTF-8")); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
} | |
buildMultipartEntity(); | |
httpentity = entity.build(); | |
} | |
// public void addStringBody(String param, String value) { | |
// if (mStringPart != null) { | |
// mStringPart.put(param, value); | |
// } | |
// } | |
private void buildMultipartEntity() { | |
entity.addPart(FILE_PART_NAME, new FileBody(mFilePart, ContentType.create("image/gif"), mFilePart.getName())); | |
if (mStringPart != null) { | |
for (Map.Entry<String, String> entry : mStringPart.entrySet()) { | |
entity.addTextBody(entry.getKey(), entry.getValue()); | |
} | |
} | |
} | |
@Override | |
public String getBodyContentType() { | |
return httpentity.getContentType().getValue(); | |
} | |
@Override | |
public byte[] getBody() throws AuthFailureError { | |
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
try { | |
httpentity.writeTo(new CountingOutputStream(bos, fileLength, | |
multipartProgressListener)); | |
} catch (IOException e) { | |
VolleyLog.e("IOException writing to ByteArrayOutputStream"); | |
} | |
return bos.toByteArray(); | |
} | |
@Override | |
protected Response<String> parseNetworkResponse(NetworkResponse response) { | |
try { | |
// System.out.println("Network Response "+ new String(response.data, "UTF-8")); | |
return Response.success(new String(response.data, "UTF-8"), | |
getCacheEntry()); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
// fuck it, it should never happen though | |
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 { | |
if (headerParams == null) { | |
headerParams = new HashMap<String, String>(1); | |
if (AppContext.userPojo != null) { | |
headerParams.put("sid", AppContext.userPojo.SID); | |
} | |
return headerParams; | |
} else { | |
if (AppContext.userPojo != null) { | |
headerParams.put("sid", AppContext.userPojo.SID); | |
} | |
} | |
return headerParams; | |
} | |
public static interface MultipartProgressListener { | |
void transferred(long transfered, int progress); | |
} | |
public static class CountingOutputStream extends FilterOutputStream { | |
private final MultipartProgressListener progListener; | |
private long transferred; | |
private long fileLength; | |
public CountingOutputStream(final OutputStream out, long fileLength, | |
final MultipartProgressListener listener) { | |
super(out); | |
this.fileLength = fileLength; | |
this.progListener = listener; | |
this.transferred = 0; | |
} | |
public void write(byte[] b, int off, int len) throws IOException { | |
out.write(b, off, len); | |
if (progListener != null) { | |
this.transferred += len; | |
int prog = (int) (transferred * 100 / fileLength); | |
this.progListener.transferred(this.transferred, prog); | |
} | |
} | |
public void write(int b) throws IOException { | |
out.write(b); | |
if (progListener != null) { | |
this.transferred++; | |
int prog = (int) (transferred * 100 / fileLength); | |
this.progListener.transferred(this.transferred, prog); | |
} | |
} | |
} | |
} |
hello, how can i use this class to upload an arraylist or a jsonarray
getBody() Throw OutOfMemoryException when I upload File more than 50MB. How to solve this? or should we use volly to handle BIG file.? Volley official say big file sucks.
I love how no one that has created these MultipartRequest classes ever creates an example of how to use these
A example of how to use please!!!!
The transferred() function in the listener is called very fast up to 100% in seconds, but the media upload takes minutes ..
Can you help us please ..
Hey i delt with sending multipart request with volley and in your case you didnt solve a serious problem
if you take a quick look of this code , The base getBody of volley request expect to return byte[] which mean that you will load all your content to the memory instead of loading chunks of data and write it on the connection's output stream
public byte[] getBody() throws AuthFailureError { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { httpentity.writeTo(new CountingOutputStream(bos, fileLength, multipartProgressListener)); } catch (IOException e) { VolleyLog.e("IOException writing to ByteArrayOutputStream"); } return bos.toByteArray(); }
to solve this issue you have to provide your own HurlStack to volly use the writeTo of your multipartEntity which will write to the outputstream
` private static void addMultipartBodyIfExists(HttpURLConnection connection, MultipartRequest<?> request)
throws IOException, AuthFailureError {
connection.setDoOutput(true);
HttpEntity entity = request.getMultiBody();
try {
connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
entity.writeTo(connection.getOutputStream());
} catch (IOException ioe) {
}
// The original code of volly
// byte[] body = request.getBody();
// if (body != null) {
// connection.setDoOutput(true);
// connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
// DataOutputStream out = new DataOutputStream(connection.getOutputStream());
// out.write(body);
// out.close();
// }
}`
@liorzam so what's the full code of the HurlStack? Did you extend HurlStack and override, or implement HttpStack and copy all the code?
And getCacheEntry()...? Any reason it's not HttpHeaderParser.parseCacheHeaders?
Hi, could you please provide a sample for uploading a image using your class above. thank you