Android volley(5)MultipartEntity 封裝 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;
- publicclass MultipartRequest extends Request<String> {
- private MultipartEntity entity = new MultipartEntity();
- privatefinal 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();
- }
- privatevoid 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
- publicbyte[] 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
- protectedvoid deliverResponse(String response) {
- mListener.onResponse(response);
- }
- }
通過這個請求就可以上傳多檔案了,也不做多解釋,程式碼也比較簡單。我也對這種方法測試過了,但是由於是和伺服器進行打交道,這裡確實沒有什麼可以展示出來,不過我還是喜歡有說服力的描述,所謂有圖有真相哈哈,上兩個圖在做解釋
這裡是從我的log截下來的兩張圖,圖一是我裝進5個相同檔案之後打印出entity的大小,顯示是8347505位元組,圖二是我裝進3個相同檔案(跟前
面5個的檔案都是一樣的)之後打印出的大小,是5005805位元組,我相