美文网首页
网络访问组件的思考四(volley简单上传下载)

网络访问组件的思考四(volley简单上传下载)

作者: zhaoyubetter | 来源:发表于2017-03-13 00:02 被阅读119次

    参考:
    http://blog.csdn.net/bboyfeiyu/article/details/42266869

    具体代码:
    https://github.com/zhaoyubetter/basenet

    Volley 框架没有提供上传下载功能,这里参考了网络上的一些资料。简单封装了一下,使其拥有了 小文件 的上传下载功能;
    大文件Volley是个坑;

    ** okhttp,上传下载大文件是没问题的,开发中推荐使用 okhttp**

    上传文件的简单封装##

    将http form表单请求报文的数据格式,用volley来模拟,实现文件上传(支持表单普通字段,与文件字段);

    class MultipartBody {
    
    
        private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    
        private final String CONTENT_TYPE = "Content-Type: ";
        private final String CONTENT_DISPOSITION = "Content-Disposition: ";
        
    
        /**
         * 字节流参数
         */
        private final String TYPE_OCTET_STREAM = "application/octet-stream";
        /**
         * 二进制参数
         */
        private final byte[] BINARY_ENCODING = "Content-Transfer-Encoding: binary\r\n\r\n".getBytes();
    
        /**
         * 换行符
         */
        private final String NEW_LINE_STR = "\r\n";
    
        /**
         * 分隔符
         */
        private String mBoundary = null;
        /**
         * 输出流
         */
        ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
    
    
        private StringBuilder mSb = new StringBuilder();
    
    
        public MultipartBody() {
            this.mBoundary = generateBoundary();
        }
    
        /**
         * 生成分隔符
         *
         * @return
         */
        private String generateBoundary() {
            final StringBuffer buf = new StringBuffer();
            final Random rand = new Random();
            for (int i = 0; i < 30; i++) {
                buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
            }
            return buf.toString();
        }
    
        /**
         * 开头分隔符
         * --WebKitFormBoundaryMcD0BA59mk3aFx4I
         */
        private void writeFirstBoundary() throws IOException {
            mOutputStream.write(("--" + mBoundary + NEW_LINE_STR).getBytes());
            mSb.append(("--" + mBoundary + NEW_LINE_STR));
        }
    
        /**
         * 添加文本参数
         */
        public void addStringPart(String paramName, String paramValue) {
            // writeToOutputStream(paramName, paramValue.getBytes(), TYPE_TEXT_CHARSET, BIT_ENCODING, "");
            writeToOutputStream(paramName, paramValue.getBytes(), null, null, "");
        }
    
        /**
         * 添加二进制参数, 例如Bitmap的字节流参数
         *
         * @param paramName
         * @param rawData
         */
        public void addBinaryPart(String paramName, final byte[] rawData) {
            writeToOutputStream(paramName, rawData, TYPE_OCTET_STREAM, BINARY_ENCODING, "no-file");
        }
    
        /**
         * 添加文件参数,可以实现文件上传功能
         *
         * @param key
         * @param file
         */
        public void addFilePart(final String key, final File file) {
            InputStream fin = null;
            try {
                fin = new FileInputStream(file);
                writeFirstBoundary();
                mOutputStream.write(getContentDispositionBytes(key, file.getName()));
                final String type = CONTENT_TYPE + TYPE_OCTET_STREAM + NEW_LINE_STR;
                mOutputStream.write(type.getBytes());
                mOutputStream.write(NEW_LINE_STR.getBytes());
    
                final byte[] tmp = new byte[4096];
                int len = 0;
                while ((len = fin.read(tmp)) != -1) {
                    mOutputStream.write(tmp, 0, len);
                }
                mOutputStream.write(NEW_LINE_STR.getBytes());
                mOutputStream.flush();
            } catch (final IOException e) {
                e.printStackTrace();
            } finally {
                closeSilently(fin);
            }
        }
    
    
        /**
         * 将数据写入到输出流中
         *
         * @param paramName
         * @param rawData
         * @param type
         * @param encodingBytes
         * @param fileName
         */
        private void writeToOutputStream(String paramName,
                                         byte[] rawData,
                                         String type,
                                         byte[] encodingBytes,
                                         String fileName) {
            try {
                writeFirstBoundary();
                if (type != null && type.length() > 0) {
                    mOutputStream.write((CONTENT_TYPE + type + NEW_LINE_STR).getBytes());
                }
                mOutputStream.write(getContentDispositionBytes(paramName, fileName));
                mOutputStream.write(NEW_LINE_STR.getBytes());
                mSb.append(new String(rawData));
    
                if (encodingBytes != null) {
                    mOutputStream.write(encodingBytes);
                }
    
                mOutputStream.write(rawData);
                mOutputStream.write(NEW_LINE_STR.getBytes());
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    
        private byte[] getContentDispositionBytes(String paramName, String fileName) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(CONTENT_DISPOSITION + "form-data; name=\"" + paramName + "\"");
            if (!TextUtils.isEmpty(fileName)) {
                stringBuilder.append("; filename=\"" + fileName + "\"");
            }
            return stringBuilder.append(NEW_LINE_STR).toString().getBytes();
        }
    
    
        public long getContentLength() {
            return mOutputStream.toByteArray().length;
        }
    
        // Content-Type: multipart/form-data; boundary=
        public String getContentType() {
            return "multipart/form-data; boundary=" + mBoundary;
        }
    
        public void writeTo(final OutputStream outstream) throws IOException {
            // 参数最末尾的结束符
            final String endString = "--" + mBoundary + "--" + NEW_LINE_STR;
            // 写入结束符
            mOutputStream.write(endString.getBytes());
            outstream.write(mOutputStream.toByteArray());
        }
    
    
        private void closeSilently(Closeable closeable) {
            try {
                if (closeable != null) {
                    closeable.close();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    新增类 PostUploadRequest,实现request:

    class PostUploadRequest extends Request<String> {
    
        private Response.Listener mListener;
    
        private MultipartBody mMultiPartEntity = new MultipartBody();
    
        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse response) {
            String parsed = "";
            try {
                parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            } catch (UnsupportedEncodingException e) {
                parsed = new String(response.data);
            }
            return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    
        }
    
        @Override
        protected void deliverResponse(String response) {
            if (mListener != null) {
                mListener.onResponse(response);
            }
        }
    
        public Map<String, File> getUploadFiles() {
            return null;
        }
    
        public PostUploadRequest(int method, String url, Response.ErrorListener listener, Response.Listener mListener) {
            super(method, url, listener);
            this.mListener = mListener;
            // 超时设置 10 分钟
            setRetryPolicy(new DefaultRetryPolicy(10 * 60 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
            setShouldCache(false);
        }
    
    
        /**
         * 请求体
         *
         * @return
         * @throws AuthFailureError
         */
        @Override
        public byte[] getBody() throws AuthFailureError {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                // 参数部分
                Map<String, String> params = getParams();
                if (params != null && params.size() > 0) {
                    for (Map.Entry<String, String> entry : params.entrySet()) {
                        mMultiPartEntity.addStringPart(entry.getKey(), entry.getValue());
                    }
                }
    
    //          // 文件部分
                final Map<String, File> uploadFiles = getUploadFiles();
                if (uploadFiles != null && uploadFiles.size() > 0) {
                    for (Map.Entry<String, File> entry : uploadFiles.entrySet()) {
                        mMultiPartEntity.addFilePart(entry.getKey(), entry.getValue());
                    }
                }
    
                // multipart body
                mMultiPartEntity.writeTo(bos);
            } catch (IOException e) {
                throw new AuthFailureError(e.getMessage());
            }
            return bos.toByteArray();
        }
    
        @Override
        public String getBodyContentType() {
            return mMultiPartEntity.getContentType();
        }
    }
    

    在 VolleyRequest类中使用:

    private void upload() {
            mRequest = new PostUploadRequest(Request.Method.POST, mUrl, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    if (mCallBack != null) {
                        mCallBack.onFailure(error);
                    }
                }
            }, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    if (mCallBack != null) {
                        mCallBack.onSuccess(response);
                    }
                }
            }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> superHeader = super.getHeaders();
                    if (mHeader != null && mHeader.size() > 0) {
                        superHeader = mHeader;
                    }
                    return superHeader;
                }
    
                // 设置Body参数
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> tParams = super.getParams();
                    if (mParams != null && mParams.size() > 0) {
                        tParams = mParams;
                    }
                    return tParams;
                }
    
                @Override
                public Map<String, File> getUploadFiles() {
                    return mUploadFiles;
                }
            };
    
            mRequest.setTag(mTag);
            requestQueue.add(mRequest);
        }
    

    下载文件的简单封装##

    新增DownRequest实现Request类:

    public class DownRequest extends Request<byte[]> {
    
        private final Response.Listener<byte[]> mListener;
    
        public DownRequest(int method, String url, Response.ErrorListener listener, Response.Listener<byte[]> downListener) {
            super(method, url, listener);
            this.mListener = downListener;
            setShouldCache(false);
        }
    
        @Override
        protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
            return Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response));
        }
    
        @Override
        protected void deliverResponse(byte[] response) {
            if (null != mListener) {
                mListener.onResponse(response);
            }
        }
    }
    

    下载实现:

    private void down() {
            mRequest = new DownRequest(Request.Method.GET, mUrl, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    if (mCallBack != null) {
                        mCallBack.onFailure(error);
                    }
                }
            }, new Response.Listener<byte[]>() {
                @Override
                public void onResponse(byte[] response) {
                    try {
                        FileUtils.saveFile(response, mDownFile);
                        if (mCallBack != null) {
                            mCallBack.onSuccess(response);
                        }
                    } catch (Exception e) {
                        if (mCallBack != null) {
                            mCallBack.onFailure(e);
                        }
                    }
                }
            }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> superHeader = super.getHeaders();
                    if (mHeader != null && mHeader.size() > 0) {
                        superHeader = mHeader;
                    }
                    return superHeader;
                }
    
                // 设置Body参数
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> tParams = super.getParams();
                    if (mParams != null && mParams.size() > 0) {
                        tParams = mParams;
                    }
                    return tParams;
                }
            };
    
            mRequest.setTag(mTag);
            requestQueue.add(mRequest);
        }
    

    相关文章

      网友评论

          本文标题:网络访问组件的思考四(volley简单上传下载)

          本文链接:https://www.haomeiwen.com/subject/ytaxnttx.html