使用volley请求数据很简便,但遇到上传文件就麻烦那可不好,同时使用多个网络请求类库也是不太建议的。所以这里就给出了一种解决方法,也要借助一个jar包,这里用到的是httpmime(点击下载),主要用到的是MultipartEntity类,可以对请求参数进行封装。
主要是继承volley的Request类,然后通过使用httpmim的MultipartEntity类对文件参数进行封装,这里实现了一个参数名对应一个文件,
一个参数名对应多个文件,如果还要多个参数名对应多个文件可以自己试着实现一下哈
package com.hrtac.testupload; import android.util.Log; 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.android.volley.toolbox.HttpHeaderParser; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; 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; /** * 功能: * * @author yanzi E-mail: [email protected] * @version 创建时间: 2015-08-09 下午4:32 */ public class MultipartRequest extends Request{ private MultipartEntity entity = new MultipartEntity(); private Response.Listener mListener; private List mFileParts; private String mFilePartName; private Map , String> mParams; /** * 单个文件+参数 上传 * @param url * @param listener * @param errorListener * @param filePartName * @param file * @param params */ public MultipartRequest(String url, Response.Listener listener, Response.ErrorListener errorListener, String filePartName, File file, Map , String> params){ super(Method.POST, url, errorListener); mFileParts = new ArrayList (); if(file != null && file.exists()){ mFileParts.add(file); }else{ VolleyLog.e("MultipartRequest---file not found"); } mFilePartName = filePartName; mListener = listener; mParams = params; buildMultipartEntity(); } /** * 多个文件+参数上传 * @param url * @param listener * @param errorListener * @param filePartName * @param files * @param params */ public MultipartRequest(String url,Response.Listener listener,Response.ErrorListener errorListener , String filePartName,List files, Map , String> params) { super(Method.POST, url, errorListener); mFilePartName = filePartName; mListener = listener; mFileParts = files; mParams = params; buildMultipartEntity(); } @Override protected Response 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) { mListener.onResponse(response); } @Override public Map , String> getHeaders() throws AuthFailureError { Map , String> headers = super.getHeaders(); if (headers == null || headers.equals(Collections.emptyMap())) { headers = new HashMap , String>(); } return headers; } @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(); } private void buildMultipartEntity() { if (mFileParts != null && mFileParts.size() > 0) { for (File file : mFileParts) { entity.addPart(mFilePartName, new FileBody(file)); } long l = entity.getContentLength(); Log.i("YanZi-volley", mFileParts.size() + "个,长度:" + l); } try { if (mParams != null && mParams.size() > 0) { for (Map.Entry , String> entry : mParams.entrySet()) { entity.addPart( entry.getKey(), new StringBody(entry.getValue(), Charset .forName("UTF-8"))); } } } catch (UnsupportedEncodingException e) { VolleyLog.e("UnsupportedEncodingException"); } } }
compile files('libs/volley.jar') compile files('libs/httpcore-4.3.2.jar') compile files('libs/httpclient-4.3.5.jar') compile files('libs/httpmime-4.3.5.jar')
private void doUploadTest(){ mSingleQueue = Volley.newRequestQueue(getApplicationContext()); String path = picPath; Log.e("zb","picPath="+picPath); String url = "http://app.sod90.com/xxx/upload/app_upload"; //换成自己的测试url地址 Map, String> params = new HashMap , String>(); params.put("id", "19"); params.put("type", "shop"); Log.e("zb","params="+params); File f1 = new File(path); Log.e("zb","f1="+f1.toString()); // File f2 = new File(path); // Log.e("zb","f2="+f2.toString()); if(!f1.exists()){ Toast.makeText(getApplicationContext(), "图片不存在,测试无效", Toast.LENGTH_SHORT).show(); return; } List f = new ArrayList (); f.add(f1); // f.add(f2); MultipartRequest request = new MultipartRequest(url, new Response.Listener () { @Override public void onResponse(String response) { Toast.makeText(getApplicationContext(), "uploadSuccess,response = " + response, Toast.LENGTH_SHORT).show(); Log.e("zb", "success,response = " + response); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), "uploadError,response = " + error.getMessage(), Toast.LENGTH_SHORT).show(); Log.e("zb", "error,response = " + error.getMessage()); } }, "f_file[]", f, params); //注意这个key必须是f_file[],后面的[]不能少 mSingleQueue.add(request); }
通过这个请求就可以上传多文件了,也不做多解释,代码也比较简单。我也对这种方法测试过了,但是由于是和服务器进行打交道,这里确实没有什么可以展示出来,不过我还是喜欢有说服力的描述,所谓有图有真相哈哈,上两个图在做解释