java - Volley : MultipartRequest. getBody:IOException 写入 ByteArrayOutputStream

标签 java android http android-studio android-volley

我正在使用 Volley 进行 API 调用。我需要将图像发布到我的服务器。

我已经尝试了很多 MultipartRequest 实现,都没有效果。

我刚刚尝试使用来自 How to send a “multipart/form-data” POST in Android with Volley 的样本通过 AZ_。

但我得到 MultipartRequest.getBody: IOException 写入 ByteArrayOutputStream 错误。

你能帮我解决我的代码吗,或者知道任何使用 Volley 上传图像的完整示例。谢谢你。

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);
            }
        }

    }
}

用户API类
   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);
    }

然后在 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);
        }
    });


}

这是我在 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'

}

最佳答案

你找到解决办法了吗?如果没有,您可以阅读我的回答 How to send a “multipart/form-data” POST in Android with Volley .我用 MultipartEntityBuilder构建零件。

如果由于弃用而不想使用 HttpEntity,请查看我的工作解决方案 Working POST Multipart Request with Volley and without HttpEntity .

希望这可以帮助!

关于java - Volley : MultipartRequest. getBody:IOException 写入 ByteArrayOutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31474585/

相关文章:

java - Graphics2D 或 2D Components 的度量单位是什么?

java - SWT - TreeViewer - 单选与多选

java - 从Android手机的SD卡中删除文件

http - Cookie 详细信息 - 名称和数据

java - 导致 java.lang.IndexOutOfBoundsException 的函数

java - Spring Boot 将 yaml 列表加载为 map

android - 注册 Android 应用程序以接收某些文件类型

android - Android 中未使用的字符串和图像资源

python - 如何在不使用任何库的情况下使用 Python 实现一个简单的 Web 服务器?

java - http url 包含数字时出错?