I am using Volley for my API call. I need to post a image to my sever.
I have tried many MultipartRequest implementation, None works.
I just tried using a sample from How to send a “multipart/form-data” POST in Android with Volley by AZ_.
But I get MultipartRequest.getBody: IOException writing to ByteArrayOutputStream Error.
Can you help me out on my code, or know any complete sample for uploading a image using Volley please. Thank you.
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;
//Code by:
//https://stackoverflow.com/questions/16797468/how-to-send-a-multipart-form-data-post-in-android-with-volley
//AZ_
//
/**
* Problems : E/Volley﹕ [17225] MultipartRequest.getBody: IOException writing to ByteArrayOutputStream
*/
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();
// it should never happen though
return Response.success(new String(response.data), getCacheEntry());
}
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
//Override getHeaders() if you want to put anything in header
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);
}
}
}
}
User API Class
public void uploadFile(String api, File file, long fileLength, String partName, final UserUploadSuccessListener listener) {
this.listener = listener;
String url = Constant.DOMAIN + api;
Map<String, String> mHeaderParams = new HashMap<String, String>();
mHeaderParams.put("pram", "pramValue");
MultipartRequest multipartRequest = new MultipartRequest
(url, errorListener, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
listener.onUserUploadFile(response);
}
}, file, fileLength, null, mHeaderParams, partName, null);
multipartRequest.setRetryPolicy(new DefaultRetryPolicy(
30000, //30 seconds - change to what you want
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
mRequestQueue.add(multipartRequest);
}
Then Call it on MainActivity:
private void test1(){
File file = new File("path:/storage/emulated/0/copy_folder/Magazine/images/assets/images/img_0007.jpg");
long fileLength = file.length();
new UserApi().uploadFile("upload", file, fileLength, "imgPost", new UserApi.UserUploadSuccessListener() {
@Override
public void onUserUploadFile(String response) {
text.setText("uploadImage() - onUserUploadFile -> \n " + response.toString());
}
@Override
public void onError(VolleyError error) {
text.setText("uploadImage() - onError -> \n " + error.toString());
}
@Override
public void onResponseError(String message) {
text.setText("uploadImage() - onResponseError -> \n " + message);
}
});
}
Here are my dependencies in Android Studio:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.google.code.gson:gson:2.3'
compile 'com.mcxiaoke.volley:library:1.0.+'
compile('org.apache.httpcomponents:httpmime:4.3.6') {
exclude module: 'httpclient'
}
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
}
Have you found the solution yet? If not, you can have a read at my answer at How to send a “multipart/form-data” POST in Android with Volley . I use MultipartEntityBuilder
to build the parts.
If don't wanna use HttpEntity because of deprecation, please take a look at my working solution Working POST Multipart Request with Volley and without HttpEntity.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With