-
-
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); | |
| } | |
| } | |
| } | |
| } |
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?
I love how no one that has created these MultipartRequest classes ever creates an example of how to use these