上传头像,上传图片这个基本上都会用到。网络框架时基于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 mListItem ;
private String BOUNDARY = "--------------520-13-14"; //数据分隔线
private String MULTIPART_FORM_DATA = "multipart/form-data";
public PostUploadRequest(String url, List 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 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 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 imageList = new ArrayList();
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 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 responseListener() {
mListener = new Response.Listener() {
@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;
}
}