package cn.alphabets.light.network;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import cn.alphabets.light.log.Logger;
import cn.alphabets.light.setting.Default;
import cn.alphabets.light.util.FileUtil;
/**
* 文件上传支持
* 虽然没有使用httpclient,但是还是依赖于Apache的
* httpcore
* httpmime
* Created by lin on 14/12/3.
*/
public class AuthMultipartRequest extends Request<String> {
/** 后台接受Multipart时的名字 */
private static final String MULTIPART_BODY_NAME = "files";
private final Response.Listener<String> mListener;
private MultipartProgressListener mProgressListener;
private HttpEntity httpEntitiy;
public static interface MultipartProgressListener {
void onProgress(long transfered, int progress);
}
/**
* 文件上传构造函数
* @param url
* @param params
* @param listener
* @param errorListener
*/
public AuthMultipartRequest(
String url,
Map<String, Object> params,
Response.Listener<String> listener,
Response.ErrorListener errorListener) {
this(url, params, listener, errorListener, null);
}
public AuthMultipartRequest(
String url,
Map<String, Object> params,
Response.Listener<String> listener,
Response.ErrorListener errorListener,
MultipartProgressListener progressListener) {
super(Method.POST, url, errorListener);
mListener = listener;
mProgressListener = progressListener;
buildMultipartEntity(params);
}
/**
* 生成Entity
*/
private void buildMultipartEntity(Map<String, Object> params) {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (entry.getValue() instanceof File) {
File file = (File) entry.getValue();
String name = file.getName();
String contentType = FileUtil.getMimeTypeOfFile(file.getAbsolutePath());
builder.addBinaryBody(MULTIPART_BODY_NAME, file, ContentType.create(contentType), name);
}
if (entry.getValue() instanceof String) {
builder.addTextBody(entry.getKey(), (String) entry.getValue());
}
}
httpEntitiy = builder.build();
}
@Override
public String getBodyContentType() {
return httpEntitiy.getContentType().getValue();
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
return Response.success(new String(response.data), getCacheEntry());
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
httpEntitiy.writeTo(new CountingOutputStream(bos, httpEntitiy.getContentLength(), mProgressListener));
} catch (IOException e) {
Logger.e(e);
throw new RuntimeException("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> header = super.getHeaders();
if (header == null || header.size() == 0) {
header = new HashMap<String, String>();
if (SessionManager.getCookie() != null) {
header.put(Default.CookieName, SessionManager.getCookie());
}
}
return header;
}
/**
* 已经上传的内容大小计量器
*/
public static class CountingOutputStream extends FilterOutputStream {
private final MultipartProgressListener progListener;
private long transferred;
private long fileLength;
public CountingOutputStream(
final OutputStream out,
long fileLength,
final MultipartProgressListener listener) {
super(out);
this.fileLength = fileLength;
this.progListener = listener;
this.transferred = 0;
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
if (progListener != null) {
this.transferred += len;
int prog = (int) (transferred * 100 / fileLength);
this.progListener.onProgress(this.transferred, prog);
}
}
public void write(int b) throws IOException {
out.write(b);
if (progListener != null) {
this.transferred++;
int prog = (int) (transferred * 100 / fileLength);
this.progListener.onProgress(this.transferred, prog);
}
}
}
}