-
-
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