Volley: MultipartRequest.getBody: IOException writing to ByteArrayOutputStream
Asked Answered
E

0

6

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://mcmap.net/q/89355/-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'

}
Elgar answered 17/7, 2015 at 11:17 Comment(5)
Please provide full stack trace of your exception.Carbamate
I am using it like this pastebin.com/aBB9EZxsCarbamate
@Carbamate I think the problem is before you did not implement the headerParams ?Elgar
@Carbamate the progress bar, don't work. it goes from 2 to 100 very fast and output 100% multiple times ...Elgar
Please use official Volley library, fork from Google and better to put exact version rather than using +Carbamate

© 2022 - 2024 — McMap. All rights reserved.