参考:
http://blog.csdn.net/bboyfeiyu/article/details/42266869
具体代码:
https://github.com/zhaoyubetter/basenet
Volley 框架没有提供上传下载功能,这里参考了网络上的一些资料。简单封装了一下,使其拥有了 小文件 的上传下载功能;
大文件Volley是个坑;
** okhttp,上传下载大文件是没问题的,开发中推荐使用 okhttp**
上传文件的简单封装##
将http form表单请求报文的数据格式,用volley来模拟,实现文件上传(支持表单普通字段,与文件字段);
class MultipartBody {
private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private final String CONTENT_TYPE = "Content-Type: ";
private final String CONTENT_DISPOSITION = "Content-Disposition: ";
/**
* 字节流参数
*/
private final String TYPE_OCTET_STREAM = "application/octet-stream";
/**
* 二进制参数
*/
private final byte[] BINARY_ENCODING = "Content-Transfer-Encoding: binary\r\n\r\n".getBytes();
/**
* 换行符
*/
private final String NEW_LINE_STR = "\r\n";
/**
* 分隔符
*/
private String mBoundary = null;
/**
* 输出流
*/
ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
private StringBuilder mSb = new StringBuilder();
public MultipartBody() {
this.mBoundary = generateBoundary();
}
/**
* 生成分隔符
*
* @return
*/
private String generateBoundary() {
final StringBuffer buf = new StringBuffer();
final Random rand = new Random();
for (int i = 0; i < 30; i++) {
buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
}
return buf.toString();
}
/**
* 开头分隔符
* --WebKitFormBoundaryMcD0BA59mk3aFx4I
*/
private void writeFirstBoundary() throws IOException {
mOutputStream.write(("--" + mBoundary + NEW_LINE_STR).getBytes());
mSb.append(("--" + mBoundary + NEW_LINE_STR));
}
/**
* 添加文本参数
*/
public void addStringPart(String paramName, String paramValue) {
// writeToOutputStream(paramName, paramValue.getBytes(), TYPE_TEXT_CHARSET, BIT_ENCODING, "");
writeToOutputStream(paramName, paramValue.getBytes(), null, null, "");
}
/**
* 添加二进制参数, 例如Bitmap的字节流参数
*
* @param paramName
* @param rawData
*/
public void addBinaryPart(String paramName, final byte[] rawData) {
writeToOutputStream(paramName, rawData, TYPE_OCTET_STREAM, BINARY_ENCODING, "no-file");
}
/**
* 添加文件参数,可以实现文件上传功能
*
* @param key
* @param file
*/
public void addFilePart(final String key, final File file) {
InputStream fin = null;
try {
fin = new FileInputStream(file);
writeFirstBoundary();
mOutputStream.write(getContentDispositionBytes(key, file.getName()));
final String type = CONTENT_TYPE + TYPE_OCTET_STREAM + NEW_LINE_STR;
mOutputStream.write(type.getBytes());
mOutputStream.write(NEW_LINE_STR.getBytes());
final byte[] tmp = new byte[4096];
int len = 0;
while ((len = fin.read(tmp)) != -1) {
mOutputStream.write(tmp, 0, len);
}
mOutputStream.write(NEW_LINE_STR.getBytes());
mOutputStream.flush();
} catch (final IOException e) {
e.printStackTrace();
} finally {
closeSilently(fin);
}
}
/**
* 将数据写入到输出流中
*
* @param paramName
* @param rawData
* @param type
* @param encodingBytes
* @param fileName
*/
private void writeToOutputStream(String paramName,
byte[] rawData,
String type,
byte[] encodingBytes,
String fileName) {
try {
writeFirstBoundary();
if (type != null && type.length() > 0) {
mOutputStream.write((CONTENT_TYPE + type + NEW_LINE_STR).getBytes());
}
mOutputStream.write(getContentDispositionBytes(paramName, fileName));
mOutputStream.write(NEW_LINE_STR.getBytes());
mSb.append(new String(rawData));
if (encodingBytes != null) {
mOutputStream.write(encodingBytes);
}
mOutputStream.write(rawData);
mOutputStream.write(NEW_LINE_STR.getBytes());
} catch (final IOException e) {
e.printStackTrace();
}
}
private byte[] getContentDispositionBytes(String paramName, String fileName) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(CONTENT_DISPOSITION + "form-data; name=\"" + paramName + "\"");
if (!TextUtils.isEmpty(fileName)) {
stringBuilder.append("; filename=\"" + fileName + "\"");
}
return stringBuilder.append(NEW_LINE_STR).toString().getBytes();
}
public long getContentLength() {
return mOutputStream.toByteArray().length;
}
// Content-Type: multipart/form-data; boundary=
public String getContentType() {
return "multipart/form-data; boundary=" + mBoundary;
}
public void writeTo(final OutputStream outstream) throws IOException {
// 参数最末尾的结束符
final String endString = "--" + mBoundary + "--" + NEW_LINE_STR;
// 写入结束符
mOutputStream.write(endString.getBytes());
outstream.write(mOutputStream.toByteArray());
}
private void closeSilently(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
}
新增类 PostUploadRequest,实现request:
class PostUploadRequest extends Request<String> {
private Response.Listener mListener;
private MultipartBody mMultiPartEntity = new MultipartBody();
@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));
}
@Override
protected void deliverResponse(String response) {
if (mListener != null) {
mListener.onResponse(response);
}
}
public Map<String, File> getUploadFiles() {
return null;
}
public PostUploadRequest(int method, String url, Response.ErrorListener listener, Response.Listener mListener) {
super(method, url, listener);
this.mListener = mListener;
// 超时设置 10 分钟
setRetryPolicy(new DefaultRetryPolicy(10 * 60 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
setShouldCache(false);
}
/**
* 请求体
*
* @return
* @throws AuthFailureError
*/
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
// 参数部分
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
mMultiPartEntity.addStringPart(entry.getKey(), entry.getValue());
}
}
// // 文件部分
final Map<String, File> uploadFiles = getUploadFiles();
if (uploadFiles != null && uploadFiles.size() > 0) {
for (Map.Entry<String, File> entry : uploadFiles.entrySet()) {
mMultiPartEntity.addFilePart(entry.getKey(), entry.getValue());
}
}
// multipart body
mMultiPartEntity.writeTo(bos);
} catch (IOException e) {
throw new AuthFailureError(e.getMessage());
}
return bos.toByteArray();
}
@Override
public String getBodyContentType() {
return mMultiPartEntity.getContentType();
}
}
在 VolleyRequest类中使用:
private void upload() {
mRequest = new PostUploadRequest(Request.Method.POST, mUrl, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (mCallBack != null) {
mCallBack.onFailure(error);
}
}
}, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (mCallBack != null) {
mCallBack.onSuccess(response);
}
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> superHeader = super.getHeaders();
if (mHeader != null && mHeader.size() > 0) {
superHeader = mHeader;
}
return superHeader;
}
// 设置Body参数
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> tParams = super.getParams();
if (mParams != null && mParams.size() > 0) {
tParams = mParams;
}
return tParams;
}
@Override
public Map<String, File> getUploadFiles() {
return mUploadFiles;
}
};
mRequest.setTag(mTag);
requestQueue.add(mRequest);
}
下载文件的简单封装##
新增DownRequest实现Request类:
public class DownRequest extends Request<byte[]> {
private final Response.Listener<byte[]> mListener;
public DownRequest(int method, String url, Response.ErrorListener listener, Response.Listener<byte[]> downListener) {
super(method, url, listener);
this.mListener = downListener;
setShouldCache(false);
}
@Override
protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
return Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response));
}
@Override
protected void deliverResponse(byte[] response) {
if (null != mListener) {
mListener.onResponse(response);
}
}
}
下载实现:
private void down() {
mRequest = new DownRequest(Request.Method.GET, mUrl, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (mCallBack != null) {
mCallBack.onFailure(error);
}
}
}, new Response.Listener<byte[]>() {
@Override
public void onResponse(byte[] response) {
try {
FileUtils.saveFile(response, mDownFile);
if (mCallBack != null) {
mCallBack.onSuccess(response);
}
} catch (Exception e) {
if (mCallBack != null) {
mCallBack.onFailure(e);
}
}
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> superHeader = super.getHeaders();
if (mHeader != null && mHeader.size() > 0) {
superHeader = mHeader;
}
return superHeader;
}
// 设置Body参数
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> tParams = super.getParams();
if (mParams != null && mParams.size() > 0) {
tParams = mParams;
}
return tParams;
}
};
mRequest.setTag(mTag);
requestQueue.add(mRequest);
}
网友评论