上傳頭像,上傳圖片這個基本上都會用到。網絡框架時基於volley的,但是volley又不能直接上傳圖片或者文件格式的文件
如果有需要的話,這裏有代碼可以拷走。可以自定義上傳的參數,如果需要可以自定義Headers
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
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.List;
import java.util.Map;
/**
* Created by gyzhong on 15/3/1.
*/
public class PostUploadRequest extends Request<String> {
/**
* 正確數據的時候回掉用,自己封裝的回掉
*/
private VolleyListenerInterface mListener ;
/*請求 數據通過參數的形式傳入*/
private List<FormImage> mListItem ;
private String BOUNDARY = "--------------520-13-14"; //數據分隔線
private String MULTIPART_FORM_DATA = "multipart/form-data";
public PostUploadRequest(String url, List<FormImage> listItem, VolleyListenerInterface listener) {
super(Method.POST, url, listener.errorListener());
this.mListener = listener ;
setShouldCache(false);
mListItem = listItem ;
//設置請求的響應事件,因爲文件上傳需要較長的時間,所以在這裏加大了,設爲5秒
setRetryPolicy(new DefaultRetryPolicy(15000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap localHashMap = new HashMap();
//可以在這裏添加Headers參數
return localHashMap;
}
/**
* 回調正確的數據
* @param response The parsed response returned by
*/
@Override
protected void deliverResponse(String response) {
mListener.onMySuccess(response);
}
@Override
public void deliverError(VolleyError error) {
//這是爲了拿到返回的錯誤碼,例如200,404,400等。有需要的可以用一下
int errorNo;
if (error != null) {
if (error.networkResponse != null) {
errorNo = error.networkResponse.statusCode;
} else {
errorNo = -1;
}
} else {
errorNo = -1;
}
MyLog.e("errorNo" + errorNo);
mListener.onMyError(error,errorNo);//這個是我自己對Volley封裝的回掉
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
@Override
public byte[] getBody() throws AuthFailureError {
if (mListItem == null||mListItem.size() == 0){
return super.getBody() ;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
int N = mListItem.size() ;
FormImage formImage ;
for (int i = 0; i < N ;i++){
formImage = mListItem.get(i) ;
StringBuffer sb= new StringBuffer() ;
/*第一行*/
//`"--" + BOUNDARY + "\r\n"`
sb.append("--"+BOUNDARY);
sb.append("\r\n") ;
/*第二行*/
//Content-Disposition: form-data; name="參數的名稱"; filename="上傳的文件名" + "\r\n"
sb.append("Content-Disposition: form-data;");
sb.append(" name=\"");
sb.append(formImage.getName()) ;
sb.append("\"") ;
sb.append("; filename=\"") ;
sb.append(formImage.getFileName()) ;
sb.append("\"");
sb.append("\r\n") ;
/*第三行*/
//Content-Type: 文件的 mime 類型 + "\r\n"
sb.append("Content-Type: ");
sb.append(formImage.getMime()) ;
sb.append("\r\n") ;
/*第四行*/
//"\r\n"
sb.append("\r\n") ;
try {
bos.write(sb.toString().getBytes("utf-8"));
/*第五行*/
//文件的二進制數據 + "\r\n"
bos.write(formImage.getValue());
bos.write("\r\n".getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
/*結尾行*/
//`"--" + BOUNDARY + "--" + "\r\n"`
String endLine = "--" + BOUNDARY + "--" + "\r\n" ;
try {
bos.write(endLine.toString().getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
return bos.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));
}
//Content-Type: multipart/form-data; boundary=----------8888888888888
@Override
public String getBodyContentType() {
return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY;
}
}
這個可以算是配置文件,裏面的指我都是寫死的,有需要的,自己修改呦
public class FormImage {
//參數的名稱
private String mName ;
//文件名
private String mFileName ;
//文件的 mime,需要根據文檔查詢
private String mMime ;
//需要上傳的圖片資源,因爲這裏測試爲了方便起見,直接把 bigmap 傳進來,真正在項目中一般不會這般做,而是把圖片的路徑傳過來,在這裏對圖片進行二進制轉換
private Bitmap mBitmap ;
public FormImage(Bitmap mBitmap) {
this.mBitmap = mBitmap;
}
public String getName() {
// return mName;
//測試,把參數名稱寫死
return "file" ;
}
public String getFileName() {
//測試,直接寫死文件的名字
return "test.png";
}
//對圖片進行二進制轉換
public byte[] getValue() {
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
mBitmap.compress(Bitmap.CompressFormat.JPEG,80,bos) ;
return bos.toByteArray();
}
//因爲我知道是 png 文件,所以直接根據文檔查的
public String getMime() {
return "image/png";
}
}
這裏是調用代碼,在獲取到圖片以後,第一個參數需要傳Bitmap過來,第二個參數是自己定義接收Volley成功失敗的回掉
public static void uploadImg(Bitmap bitmap, VolleyListenerInterface listener) {
List<FormImage> imageList = new ArrayList<FormImage>();
imageList.add(new FormImage(bitmap));
Request request = new PostUploadRequest(url, imageList, listener);
MyApplication.getRequestQueue().add(request);
/**
*MyApplication.getRequestQueue()其實這類我寫個個全局的變量
*volleyQueue = Volley.newRequestQueue(context);
*volleyQueue .add(request)
*/
}
我把我自己寫的鑑定回掉也附上吧。
/**
* Volley 請求成功的回掉
*/
public abstract class VolleyListenerInterface {
// public Context mContext;
public static Response.Listener<String> mListener;
public static Response.ErrorListener mErrorListener;
public VolleyListenerInterface() {
// this.mContext = context;
}
// 請求成功時的回調函數
public abstract void onMySuccess(String result);
// 請求失敗時的回調函數
public abstract void onMyError(VolleyError error, int errorNo);
// 創建請求的事件監聽
public Response.Listener<String> responseListener() {
mListener = new Response.Listener<String>() {
@Override
public void onResponse(String s) {
onMySuccess(s);
}
};
return mListener;
}
// 創建請求失敗的事件監聽
public Response.ErrorListener errorListener() {
mErrorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
int errorNo;
if (volleyError != null) {
if (volleyError.networkResponse != null) {
errorNo = volleyError.networkResponse.statusCode;
} else {
errorNo = -1;
}
} else {
errorNo = -1;
}
onMyError(volleyError, errorNo);
}
};
return mErrorListener;
}
}