使用volley上傳圖片,一個參數多張圖、多張圖片多張圖,親測有效哦

1、前言java

Google自從2013的IO大會上發佈volley框架以後就受到普遍應用,的確,用過幾個網絡請求庫,感受volley仍是很好用的,用起來也特別方便順手。可是遇到上傳文件就比較麻煩,尤爲是有時候想一個參數名對應多個文件,就像我坑爹後臺給個人接口,就是參數的key叫作images,而後value是多圖。。多圖。。。圖。。。。android

有許多網絡請求庫的post請求時,帶參數使用hashmap進行封裝的,可是hashmap是以鍵值對形式存值的,這裏有一個問題就是一個key對應一個value,當你連續put進去兩個key是同樣的時候,後者就會將前者取代掉。最後只剩下一個參數而已。這樣是達不到需求的。而有一個解決辦法就是開多個子線程,每次傳一張圖片過去,其實這樣也行,具體仍是看需求,我這裏要討論的是一次性傳多圖。apache


2、解決服務器

而若是使用volley的話,由於請求數據那些都很簡便,但遇到上傳文件就麻煩那可很差,同時使用多個網絡請求類庫也是不太建議的。因此這裏就給出了一種解決方法,也要藉助一個jar包,這裏用到的是httpmime(點擊下載),主要用到的是MultipartEntity類,能夠對請求參數進行封裝。網絡


主要是繼承volley的Request類,而後經過使用httpmim的MultipartEntity類對文件參數進行封裝,這裏實現了一個參數名對應一個文件,框架

一個參數名對應多個文件,若是還要多個參數名對應多個文件能夠本身試着實現一下哈
ide


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


經過這個請求就能夠上傳多文件了,也不作多解釋,代碼也比較簡單。我也對這種方法測試過了,可是因爲是和服務器進行打交道,這裏確實沒有什麼能夠展現出來,不過我仍是喜歡有說服力的描述,所謂有圖有真相哈哈,上兩個圖在作解釋post

相關文章
相關標籤/搜索