直接上代码,首先自定义的request:
public class MultipartRequest extends Request<JSONObject> {
private VolleyErrorListener errorListener = null;
private VolleyResponseListener listener = null;
private MultipartRequestParams params = null;
private HttpEntity httpEntity = null;
public MultipartRequest(String url, VolleyJsonResponseHandler handler, MultipartRequestParams params) {
this(Method.POST,params, url, handler, null);
}
public MultipartRequest(int method,MultipartRequestParams params, String url, VolleyJsonResponseHandler handler,
Context context) {
super(method, RequestUrl.BASE_URL + url, null);
// TODO Auto-generated constructor stub
this.params = params;
this.errorListener = new VolleyErrorListener(context, handler, false, this);
this.listener = new VolleyResponseListener(context, handler);
}
@Override
public byte[] getBody() throws AuthFailureError {
// TODO Auto-generated method stub
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if(params != null) {
httpEntity = params.getEntity();
try {
httpEntity.writeTo(baos);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Logger.d("IOException writing to ByteArrayOutputStream");
}
String str = new String(baos.toByteArray());
Logger.d("bodyString is :" + str);
}
return baos.toByteArray();
}
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
// TODO Auto-generated method stub
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
errorListener.setFlag(false);
return Response.error(new ParseError(response));
} catch (JSONException je) {
errorListener.setFlag(false);
return Response.error(new ParseError(response));
}
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
// TODO Auto-generated method stub
Map<String, String> headers = super.getHeaders();
if (null == headers || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
MainApplication.getInstance().addSessionCookie(headers);
return headers;
}
@Override
public String getBodyContentType() {
// TODO Auto-generated method stub
String str = httpEntity.getContentType().getValue();
return httpEntity.getContentType().getValue();
}
@Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
listener.onResponse(response);
}
@Override
public void deliverError(VolleyError error) {
// TODO Auto-generated method stub
if(errorListener != null) {
errorListener.onErrorResponse(error);
}
}
MultipartParams文件:
public class MultipartRequestParams {
protected ConcurrentHashMap<String, String> urlParams;
protected ConcurrentHashMap<String, FileWrapper> fileParams;
public MultipartRequestParams() {
init();
}
public MultipartRequestParams(String key, String value) {
init();
put(key, value);
}
private void init() {
urlParams = new ConcurrentHashMap<String, String>();
fileParams = new ConcurrentHashMap<String, FileWrapper>();
}
/**
* 添加value到request中
* @param key
* @param value
*/
public void put(String key, String value) {
if(key != null && value != null) {
urlParams.put(key, value);
}
}
/**
* 添加文件到request中
* @param key
* @param file
*/
public void put(String key, File file) {
try {
put(key, new FileInputStream(file), file.getName());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Logger.d("MultipartRequestParams file not found!!!");
}
}
/**
* 添加stream到request中
* @param key
* @param stream
* @param fileName
*/
public void put(String key, InputStream stream, String fileName) {
put(key, stream, fileName, null);
}
/**
* 添加stream到request中
* @param key
* @param stream
* @param fileName
* @param contentType
*/
public void put(String key, InputStream stream, String fileName, String contentType) {
if(key != null && stream != null) {
fileParams.put(key, new FileWrapper(stream, fileName, contentType));
}
}
public HttpEntity getEntity() {
HttpEntity entity = null;
if(!fileParams.isEmpty()) {
MultipartEntity multipartEntity = new MultipartEntity();
// Add string params
for(ConcurrentHashMap.Entry<String, String> entry : urlParams.entrySet()) {
multipartEntity.addPart(entry.getKey(), entry.getValue());
}
// Add file params
int currentIndex = 0;
int lastIndex = fileParams.entrySet().size() - 1;
for(ConcurrentHashMap.Entry<String, FileWrapper> entry : fileParams.entrySet()) {
FileWrapper file = entry.getValue();
if(file.inputStream != null) {
boolean isLast = currentIndex == lastIndex;
if(file.contentType != null) {
multipartEntity.addPart(entry.getKey(), file.getFileName(), file.inputStream, file.contentType, isLast);
} else {
multipartEntity.addPart(entry.getKey(), file.getFileName(), file.inputStream, isLast);
}
}
currentIndex++;
}
entity = multipartEntity;
}
return entity;
}
private static class FileWrapper {
public InputStream inputStream;
public String fileName;
public String contentType;
public FileWrapper(InputStream inputStream, String fileName,
String contentType) {
this.inputStream = inputStream;
this.fileName = fileName;
this.contentType = contentType;
}
public String getFileName() {
if (fileName != null) {
return fileName;
} else {
return "nofilename";
}
}
}
MultipartEntity文件:
class MultipartEntity implements HttpEntity {
private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private String boundary = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
boolean isSetLast = false;
boolean isSetFirst = false;
public MultipartEntity() {
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)]);
}
this.boundary = buf.toString();
}
public void writeFirstBoundaryIfNeeds(){
if(!isSetFirst){
try {
out.write(("--" + boundary + "\r\n").getBytes());
} catch (final IOException e) {
e.printStackTrace();
}
}
isSetFirst = true;
}
public void writeLastBoundaryIfNeeds() {
if(isSetLast){
return;
}
try {
out.write(("\r\n--" + boundary + "--\r\n").getBytes());
} catch (final IOException e) {
e.printStackTrace();
}
isSetLast = true;
}
public void addPart(final String key, final String value) {
writeFirstBoundaryIfNeeds();
try {
out.write(("Content-Disposition: form-data; name=\"" +key+"\"\r\n\r\n").getBytes());
out.write(value.getBytes());
out.write(("\r\n--" + boundary + "\r\n").getBytes());
} catch (final IOException e) {
e.printStackTrace();
}
}
public void addPart(final String key, final String fileName, final InputStream fin, final boolean isLast){
addPart(key, fileName, fin, "application/octet-stream", isLast);
}
public void addPart(final String key, final String fileName, final InputStream fin, String type, final boolean isLast){
writeFirstBoundaryIfNeeds();
try {
type = "Content-Type: "+type+"\r\n";
out.write(("Content-Disposition: form-data; name=\""+ key+"\"; filename=\"" + fileName + "\"\r\n").getBytes());
out.write(type.getBytes());
out.write("Content-Transfer-Encoding: binary\r\n\r\n".getBytes());
final byte[] tmp = new byte[4096];
int l = 0;
while ((l = fin.read(tmp)) != -1) {
out.write(tmp, 0, l);
}
if(!isLast)
out.write(("\r\n--" + boundary + "\r\n").getBytes());
else {
writeLastBoundaryIfNeeds();
}
out.flush();
} catch (final IOException e) {
e.printStackTrace();
} finally {
try {
fin.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
public void addPart(final String key, final File value, final boolean isLast) {
try {
addPart(key, value.getName(), new FileInputStream(value), isLast);
} catch (final FileNotFoundException e) {
e.printStackTrace();
}
}
@Override
public long getContentLength() {
writeLastBoundaryIfNeeds();
return out.toByteArray().length;
}
@Override
public Header getContentType() {
return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
}
@Override
public boolean isChunked() {
return false;
}
@Override
public boolean isRepeatable() {
return false;
}
@Override
public boolean isStreaming() {
return false;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
outstream.write(out.toByteArray());
}
@Override
public Header getContentEncoding() {
return null;
}
@Override
public void consumeContent() throws IOException,
UnsupportedOperationException {
if (isStreaming()) {
throw new UnsupportedOperationException(
"Streaming entity does not implement #consumeContent()");
}
}
@Override
public InputStream getContent() throws IOException,
UnsupportedOperationException {
return new ByteArrayInputStream(out.toByteArray());
}
其实MultipartParams和MultipartEntity主要都是用开源的AsyncHttpClient里面的源文件