http://my.oschina.net/u/1177694/blog/491834

本文介绍如何使用Volley框架一次性上传多个文件,并提供了一个自定义请求类MultipartRequest的实现方式,该类能够处理单个参数对应多个文件的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 使用volley上传图片,一个参数多张图、多张图片多张图,亲测有效哦


一、前言

Google自从2013的IO大会上发布volley框架之后就受到广泛应用,的确,用过几个网络请求库,感觉volley还是很好用的,用起来也特别方便顺手。但是遇到上传文件就比较麻烦,尤其是有时候想一个参数名对应多个文件,就像我坑爹后台给我的接口,就是参数的key叫做images,然后value是多图。。多图。。。图。。。。

有许多网络请求库的post请求时,带参数使用hashmap进行封装的,但是hashmap是以键值对形式存值的,这里有一个问题就是一个key对应一个value,当你连续put进去两个key是一样的时候,后者就会将前者取代掉。最后只剩下一个参数而已。这样是达不到需求的。而有一个解决办法就是开多个子线程,每次传一张图片过去,其实这样也行,具体还是看需求,我这里要讨论的是一次性传多图。


二、解决

而如果使用volley的话,因为请求数据那些都很简便,但遇到上传文件就麻烦那可不好,同时使用多个网络请求类库也是不太建议的。所以这里就给出了一种解决方法,也要借助一个jar包,这里用到的是httpmime(点击下载),主要用到的是MultipartEntity类,可以对请求参数进行封装。


主要是继承volley的Request类,然后通过使用httpmim的MultipartEntity类对文件参数进行封装,这里实现了一个参数名对应一个文件,

一个参数名对应多个文件,如果还要多个参数名对应多个文件可以自己试着实现一下哈


package com.android.volley.toolbox;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

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;
import com.common.utils.CLog;
import com.common.utils.FileUtil;

public class MultipartRequest extends Request<String{

    private MultipartEntity entity = new MultipartEntity();

    private final Response.Listener<String> mListener;

    private List<File> mFileParts;
    private String mFilePartName;
    private Map<String, String> mParams;
    /**
     * 单个文件
     * @param url
     * @param errorListener
     * @param listener
     * @param filePartName
     * @param file
     * @param params
     */
    public MultipartRequest(String url, Response.ErrorListener errorListener,
            Response.Listener<String> listener, String filePartName, File file,
            Map<String, String> params) {
        super(Method.POST, url, errorListener);

        mFileParts = new ArrayList<File>();
        if (file != null) {
            mFileParts.add(file);
        }
        mFilePartName = filePartName;
        mListener = listener;
        mParams = params;
        buildMultipartEntity();
    }
    /**
     * 多个文件,对应一个key
     * @param url
     * @param errorListener
     * @param listener
     * @param filePartName
     * @param files
     * @param params
     */
    public MultipartRequest(String url, Response.ErrorListener errorListener,
            Response.Listener<String> listener, String filePartName,
            List<File> files, Map<String, String> params) {
        super(Method.POST, url, errorListener);
        mFilePartName = filePartName;
        mListener = listener;
        mFileParts = files;
        mParams = params;
        buildMultipartEntity();
    }

    private void buildMultipartEntity() {
        if (mFileParts != null && mFileParts.size() > 0) {
            for (File file : mFileParts) {
                entity.addPart(mFilePartName, new FileBody(file));
            }
            long l = entity.getContentLength();
            CLog.log(mFileParts.size()+"个,长度:"+l);
        }

        try {
            if (mParams != null && mParams.size() > 0) {
                for (Map.Entry<String, String> entry : mParams.entrySet()) {
                    entity.addPart(
                            entry.getKey(),
                            new StringBody(entry.getValue(), Charset
                                    .forName("UTF-8")));
                }
            }
        } catch (UnsupportedEncodingException e) {
            VolleyLog.e("UnsupportedEncodingException");
        }
    }

    @Override
    public String getBodyContentType() {
        return entity.getContentType().getValue();
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            entity.writeTo(bos);
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        CLog.log("parseNetworkResponse");
        if (VolleyLog.DEBUG) {
            if (response.headers != null) {
                for (Map.Entry<String, String> entry : response.headers
                        .entrySet()) {
                    VolleyLog.d(entry.getKey() + "=" + entry.getValue());
                }
            }
        }

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


    /*
     * (non-Javadoc)
     * 
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        VolleyLog.d("getHeaders");
        Map<String, String> headers = super.getHeaders();

        if (headers == null || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }


        return headers;
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }
}


通过这个请求就可以上传多文件了,也不做多解释,代码也比较简单。我也对这种方法测试过了,但是由于是和服务器进行打交道,这里确实没有什么可以展示出来,不过我还是喜欢有说服力的描述,所谓有图有真相哈哈,上两个图在做解释

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值