• 使用Volley上传文件


    使用浏览器上传文件,然后通过Wireshark抓包分析,发现发送的数据大概是这个样子。

    MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "----WebKitFormBoundary1UBMMKIkN58civN4"
        [Type: multipart/form-data]
        First boundary: ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part: 
            Content-Disposition: form-data; name="name"
    
    
            Data (16 bytes)
        Boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part:  (image/png)
            Content-Disposition: form-data; name="photo[]"; filename="Screenshot (2).png"
    
            Content-Type: image/png
    
    
            Portable Network Graphics
        Boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part:  (image/png)
        Boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part:  (image/png)
        Boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part:  (image/png)
        Boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4
    
        Encapsulated multipart part:  (image/png)
        Last boundary: 
    ------WebKitFormBoundary1UBMMKIkN58civN4--
    
    

     首先来自定义一个HttpEntity,

    package cc.dewdrop.volleydemo.utils;
    
    import com.android.volley.VolleyLog;
    
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.message.BasicHeader;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.Closeable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.activation.MimetypesFileTypeMap;
    
    /**
     * Created by Tingkuo on 12/1/2015.
     */
    public class FileUploadEntity implements HttpEntity {
    
        private static final String TAG = FileUploadEntity.class.getSimpleName();
    
        private static final String BOUNDARY = "__FILE_UPLOAD_ENTITY__";
    
        private ByteArrayOutputStream mOutputStream;
    
        public FileUploadEntity() {
            mOutputStream = new ByteArrayOutputStream();
    
            try {
                writeFirstBoundary();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void writeFirstBoundary() throws IOException {
            VolleyLog.e("writeFirstBoundary");
            mOutputStream.write(("--" + BOUNDARY + "
    ").getBytes());
            mOutputStream.write(("Content-Disposition: form-data; name="" + "name" + ""
    
    ").getBytes());
            mOutputStream.write("Content-Transfer-Encoding: binary
    
    ".getBytes());
            mOutputStream.flush();
        }
    
    
        private void writeLastBoundary() throws IOException {
            VolleyLog.e("writeLastBoundary");
            mOutputStream.write(("
    --" + BOUNDARY + "--
    ").getBytes());
        }
    
        public void addFile(final String key, final File file) {
            VolleyLog.e("addFile");
            InputStream inputStream = null;
    
            try {
                mOutputStream.write(("
    --" + BOUNDARY + "
    ").getBytes());
    
                StringBuilder stringBuilderContentDisposition = new StringBuilder();
                stringBuilderContentDisposition.append("Content-Disposition: ");
                stringBuilderContentDisposition.append("form-data; ");
                stringBuilderContentDisposition.append("name="" + key + ""; ");
                stringBuilderContentDisposition.append("filename="" + file.getName() + ""
    ");
                mOutputStream.write(stringBuilderContentDisposition.toString().getBytes());
    
                StringBuilder stringBuilderContentType = new StringBuilder();
                stringBuilderContentType.append("Content-Type: ");
                stringBuilderContentType.append(new MimetypesFileTypeMap().getContentType(file).toString());
                stringBuilderContentType.append("
    
    ");
                mOutputStream.write(stringBuilderContentType.toString().getBytes());
    
                inputStream = new FileInputStream(file);
                final byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = inputStream.read(buffer)) != -1) {
                    VolleyLog.e("len --> %s", String.valueOf(len));
                    mOutputStream.write(buffer, 0, len);
                }
                VolleyLog.e("===last====len --> %s", String.valueOf(len));
    
                mOutputStream.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                closeSilently(inputStream);
            }
        }
    
        private void closeSilently(Closeable closeable) {
            try {
                if (closeable != null) {
                    closeable.close();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public boolean isRepeatable() {
            return false;
        }
    
        @Override
        public boolean isChunked() {
            return false;
        }
    
        @Override
        public long getContentLength() {
            return mOutputStream.toByteArray().length;
        }
    
        @Override
        public Header getContentType() {
            return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
        }
    
        @Override
        public Header getContentEncoding() {
            return null;
        }
    
        @Override
        public InputStream getContent() throws IOException, UnsupportedOperationException {
            return new ByteArrayInputStream(mOutputStream.toByteArray());
        }
    
        @Override
        public void writeTo(OutputStream outputStream) throws IOException {
            writeLastBoundary();
            outputStream.write(mOutputStream.toByteArray());
        }
    
        @Override
        public boolean isStreaming() {
            return false;
        }
    
        @Override
        public void consumeContent() throws IOException {
    
        }
    }
    

    现在来解释一下,首先这是支持多文件上传的,数据格式一共包括四部分,Content-Type,First boundary,文件二进制数据[],及Last boundary。可以有多个文件,使用addFile方法插入,文件之间需要有分隔符Boundary。每个文件需要有Content-Disposition及Content-Type

    然后再自定义一个Request,根据需要使用不同的构造方法

    package cc.dewdrop.volleydemo.utils;
    
    import com.android.volley.AuthFailureError;
    import com.android.volley.NetworkResponse;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.Listener;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.toolbox.HttpHeaderParser;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by Tingkuo on 12/2/2015.
     */
    public class FileUploadRequest extends Request<String> {
        private final Listener<String> mListener;
    
        private FileUploadEntity mFileUploadEntity = new FileUploadEntity();
        private Map<String, String> mHeaders = new HashMap<>();
    
    
        public FileUploadRequest(String url, Listener<String> listener) {
            this(url, listener, null);
        }
    
        public FileUploadRequest(String url, Listener<String> listener, ErrorListener errorListener) {
            this(Method.POST, url, listener, errorListener);
        }
    
        public FileUploadRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) {
            super(method, url, errorListener);
            this.mListener = listener;
        }
    
        public FileUploadEntity getFileUploadEntity() {
            return mFileUploadEntity;
        }
    
        @Override
        public String getBodyContentType() {
            return mFileUploadEntity.getContentType().getValue();
        }
    
        public void addHeader(String key, String value) {
            mHeaders.put(key, value);
        }
    
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            return mHeaders;
        }
    
        @Override
        public byte[] getBody() throws AuthFailureError {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            try {
                mFileUploadEntity.writeTo(outputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return outputStream.toByteArray();
        }
    
        @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);
            }
        }
    }
    

    代码是放在Volley中其他类型Request来写的,没什么好说的。

    最后就是如何调用

        private void simpleUploadFile() {
            File file = new File(Environment.getExternalStorageDirectory().getPath() + "/upload.png");
    
            fileUploadRequest = new FileUploadRequest(
                    Request.Method.POST,
                    urlList.get(2),
                    new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            textViewInfo.setText("Post Succeed:
    " + response.replace("<br>", "
    "));
                            Log.e(TAG, response);
                            dialog.dismiss();
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            textViewInfo.setText("Post Failed:
    " + error.getMessage());
                            Log.e(TAG, error.getMessage());
                            dialog.dismiss();
                        }
                    }
            );
            fileUploadRequest.addHeader("User-Agent", "Android 5.1.1");
            FileUploadEntity fileUploadEntity = fileUploadRequest.getFileUploadEntity();
            fileUploadEntity.addFile("file[]", file);
            fileUploadEntity.addFile("file[]", file);
            fileUploadEntity.addFile("file[]", file);
            fileUploadEntity.addFile("file[]", file);
            fileUploadEntity.addFile("file[]", file);
            requestQueue.add(fileUploadRequest);
    
            dialog.show();
        }
    

    实例化一个新的Request对象,传入Method,Url,然后通过Request对象来获取Entity,通过addFile()方法来传入需要上传的文件,最后加入requestQueue,使用方法与其他类型Request相同。

    备注:

    需要添加以下依赖:

        compile 'org.apache.httpcomponents:httpcore:4.4.4'
        compile 'org.apache.httpcomponents:httpmime:4.5.1'
        compile files('libs/volley.jar')
        compile files('libs/activation.jar')
    

      

  • 相关阅读:
    IE Only的userData 简单
    IE userdata 原理 应用 详解 简单
    shell命令执行顺序 简单
    Linux split命令实例 简单
    PHP中调用系统命令的system(),exec(),passthr 简单
    HTML5 LocalStorage 本地存储 简单
    linux 下查看机器配置命令 简单
    《高效能人士的七个习惯》读书笔记 简单
    poj 1042(贪心)
    poj 2485 Highways (prim)
  • 原文地址:https://www.cnblogs.com/zhangtingkuo/p/5013413.html
Copyright © 2020-2023  润新知