1.代碼使用
RequestQueue queue = Volley.newRequestQueue(context);
MultipartRequest multipartRequest = new MultipartRequest(
url, new Response.Listener<String>() {
@Override
public void onResponse(String string) {
//string爲服務器返回的字符串
Toast.makeText(context, "更新成功", Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context,"失敗",Toast.LENGTH_SHORT).show();
}
});
// 添加header
multipartRequest.addHeader("header-name", "value");
// 通過MultipartEntity來設置參數
MultipartEntity multi = multipartRequest.getMultiPartEntity();
//傳參數
multi.addStringPart("userId", userId());
//傳二進制byte[]
multi.addBinaryPart("logo", bytes);
//傳文件(以圖片爲例)
multi.addFilePart("logo", BitmapToUtils.saveFile(head),"image/png");
queue.add(multipartRequest);
2.自定義Request類
package com.gonghoo.Multipart;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
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.Map;
/**
* 上傳參數,二進制,文件自定義Request類
* yaoyuan
*/
public class MultipartRequest extends Request<String> {
MultipartEntity mMultiPartEntity = new MultipartEntity();
Map<String, String> mHeaders = new HashMap<String, String>();
private final Response.Listener<String> mListener;
/**
* Creates a new request with the given url.
*
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
*/
public MultipartRequest(String url, Response.Listener<String> listener) {
this(url, listener, null);
}
/**
* Creates a new POST request.
*
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
public MultipartRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
mListener = listener;
}
/**
* @return
*/
public MultipartEntity getMultiPartEntity() {
return mMultiPartEntity;
}
@Override
public String getBodyContentType() {
return mMultiPartEntity.getContentType().getValue();
}
public void addHeader(String key, String value) {
mHeaders.put(key, value);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return mHeaders;
}
@Override
public byte[] getBody() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
// multipart body
mMultiPartEntity.writeTo(bos);
} catch (IOException e) {
Log.e("", "IOException writing to ByteArrayOutputStream");
}
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));
}
@Override
protected void deliverResponse(String response) {
if (mListener != null) {
mListener.onResponse(response);
}
}
}
3.自定義HttpEntity類(關鍵類,可以自己定製,我的是以圖片png爲例)
package com.gonghoo.Multipart;
import android.text.TextUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicHeader;
import java.io.*;
import java.util.Random;
/**
* 上傳參數,二進制,文件自定義HttpEntity類
* yaoyuan
*/
public class MultipartEntity implements HttpEntity {
//參數,二進制,文件上傳自定義HttpEntity類 yaoyuan
private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
.toCharArray();
/**
* 換行符
*/
private final String NEW_LINE_STR = "\r\n";
private final String CONTENT_TYPE = "Content-Type: ";
private final String CONTENT_DISPOSITION = "Content-Disposition: ";
/**
* 文本參數和字符集
*/
private final String TYPE_TEXT_CHARSET = "text/plain; charset=UTF-8";
/**
* 字節流參數
*/
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 byte[] BIT_ENCODING = "Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes();
/**
* 分隔符
*/
private String mBoundary = null;
/**
* 輸出流
*/
ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
public MultipartEntity() {
this.mBoundary = generateBoundary();
}
/**
* 生成分隔符
*
* @return
*/
private final 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();
}
/**
* 參數開頭的分隔符
*
* @throws IOException
*/
private void writeFirstBoundary() throws IOException {
mOutputStream.write(("--" + mBoundary + "\r\n").getBytes());
}
/**
* 添加文本參數
*
* @param value
*/
public void addStringPart(final String paramName, final String value) {
writeToOutputStream(paramName, value.getBytes(), TYPE_TEXT_CHARSET, BIT_ENCODING, "");
}
/**
* 將數據寫入到輸出流中
*
* @param rawData
* @param type
* @param encodingBytes
* @param fileName
*/
private void writeToOutputStream(String paramName, byte[] rawData, String type,
byte[] encodingBytes,
String fileName) {
try {
writeFirstBoundary();
mOutputStream.write((CONTENT_TYPE + type + NEW_LINE_STR).getBytes());
mOutputStream
.write(getContentDispositionBytes(paramName, fileName));
mOutputStream.write(encodingBytes);
mOutputStream.write(rawData);
mOutputStream.write(NEW_LINE_STR.getBytes());
} catch (final IOException e) {
e.printStackTrace();
}
}
/**
* 添加二進制參數, 例如Bitmap的字節流參數
*
* @param rawData
*/
public void addBinaryPart(String paramName, final byte[] rawData,final String filetype) {
writeToOutputStream(paramName, rawData, filetype, BINARY_ENCODING, "no-file");
}
/**
* 添加文件參數,可以實現文件上傳功能
*
* @param key
* @param file
*/
public void addFilePart(final String key, final File file ,final String filetype) {
InputStream fin = null;
try {
fin = new FileInputStream(file);
writeFirstBoundary();
final String type = CONTENT_TYPE + filetype + NEW_LINE_STR;
mOutputStream.write(getContentDispositionBytes(key, file.getName()));
mOutputStream.write(type.getBytes());
mOutputStream.write(BINARY_ENCODING);
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);
}
}
private void closeSilently(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} 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 + "\"");
// 文本參數沒有filename參數,設置爲空即可
if (!TextUtils.isEmpty(fileName)) {
stringBuilder.append("; filename=\""
+ fileName + "\"");
}
return stringBuilder.append(NEW_LINE_STR).toString().getBytes();
}
@Override
public long getContentLength() {
return mOutputStream.toByteArray().length;
}
@Override
public Header getContentType() {
return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + mBoundary);
}
@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 {
// 參數最末尾的結束符
final String endString = "--" + mBoundary + "--\r\n";
// 寫入結束符
mOutputStream.write(endString.getBytes());
//
outstream.write(mOutputStream.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() {
return new ByteArrayInputStream(mOutputStream.toByteArray());
}
}
4.可以debug看報文的格式,要嚴格按照要求來,該轉行就轉行