如何在Android Volley Library中使用MultiPart上传图像文件阵列
问题描述:
我只是Android应用程序开发的初学者。如何在Android Volley Library中使用MultiPart上传图像文件阵列
我想使用Android Volley库上传图像文件。
我已经用在一些博客的某个地方发现了这个辅助类:
public class VolleyMultiPartRequest extends Request<NetworkResponse> {
private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();
private Response.Listener<NetworkResponse> mListener;
private Response.ErrorListener mErrorListener;
private Map<String, String> mHeaders;
SharedPreferencesManager sharedPreferencesManager =null;
public VolleyMultiPartRequest(int method, String url,
Response.Listener<NetworkResponse> listener,
Response.ErrorListener errorListener, Context context) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
this.sharedPreferencesManager = new SharedPreferencesManager(context);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
headers.put("Authorization", "Bearer " + sharedPreferencesManager.retreiveString(AppText.ACCESS_TOKEN));
headers.put("Content-Type", "multipart/form-data");
return headers;
}
@Override
public String getBodyContentType() {
return "multipart/form-data;boundary=" + boundary;
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
try {
// populate text payload
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
textParse(dos, params, getParamsEncoding());
}
// populate data byte payload
Map<String, DataPart> data = getByteData();
if (data != null && data.size() > 0) {
dataParse(dos, data);
}
// close multipart form data after text and file data
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected Map<String, DataPart> getByteData() throws AuthFailureError {
return null;
}
@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(
response,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
}
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + encoding, uee);
}
}
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
for (Map.Entry<String, DataPart> entry : data.entrySet()) {
buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
}
}
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(parameterValue + lineEnd);
}
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
}
dataOutputStream.writeBytes(lineEnd);
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024 * 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dataOutputStream.writeBytes(lineEnd);
}
public class DataPart {
private String fileName;
private byte[] content;
private String type;
public DataPart() {
}
public DataPart(String name, byte[] data) {
fileName = name;
content = data;
}
String getFileName() {
return fileName;
}
byte[] getContent() {
return content;
}
String getType() {
return type;
}
}
}
而且叫这个助手是这样的:
VolleyMultiPartRequest volleyMultipartRequest = new VolleyMultiPartRequest(Request.Method.POST, Api.UPLOAD_FILE,
new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
try {
JSONObject obj = new JSONObject(new String(response.data));
Toast.makeText(context, obj.getString("message"), Toast.LENGTH_SHORT).show();
successCallBack.onSuccess(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, error.getMessage(), Toast.LENGTH_SHORT).show();
try {
errorCallBack.onError(new JSONObject(""));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, context) {
/*
* If you want to add more parameters with the image
* you can do it here
* here we have only one parameter with the image
* which is tags
* */
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("file_for", "post");
params.put("file_type", "image");
return params;
}
/*
* Here we are passing image by renaming it with a unique name
* */
@Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
long imagename = System.currentTimeMillis();
params.put("images[]", new DataPart(imagename + ".png", getFileDataFromDrawable(bitmap)));
return params;
}
};
我收到服务器错误作为响应。
我尝试了不同的教程,但没有找到确切的方法和简单的解决方案。
在邮递员中,邮件头和参数是这样的,有一个图片数组,你可以在附图中看到(8张照片)。我想用volley库做完全相同的API调用。
答
试试这个代码:
我有类似的问题的种类我固定使用这个
上传multiple files in array
使用多
-
添加依赖条件
compile 'org.apache.httpcomponents:httpcore:4.2.4' compile 'org.apache.httpcomponents:httpmime:4.2' compile 'com.mcxiaoke.volley:library:1.0.19'
2.增加的gradle中
defaultConfig {
useLibrary 'org.apache.http.legacy'
}
-
Helper类AndroidMultiPartEntity.java
public class AndroidMultiPartEntity extends MultipartEntity { private final ProgressListener listener; public AndroidMultiPartEntity(final ProgressListener listener) { super(); this.listener = listener; } public AndroidMultiPartEntity(final HttpMultipartMode mode, final ProgressListener listener) { super(mode); this.listener = listener; } public AndroidMultiPartEntity(HttpMultipartMode mode, final String boundary, final Charset charset, final ProgressListener listener) { super(mode, boundary, charset); this.listener = listener; } @Override public void writeTo(final OutputStream outstream) throws IOException { super.writeTo(new CountingOutputStream(outstream, this.listener)); } public interface ProgressListener { void transferred(long num); } public static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; public CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } public void write(int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } }
-
API调用方法
private class registerCall extends AsyncTask<Void, Integer, String> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onProgressUpdate(Integer... progress) { } @Override protected String doInBackground(Void... params) { return registerMultipartCall(); } private String registerMultipartCall() { String responseString = null; HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("URL"); //UPLOAD URL try { AndroidMultiPartEntity entity = new AndroidMultiPartEntity(new AndroidMultiPartEntity.ProgressListener() { @Override public void transferred(long num) { } }); File sourceFile = new File(filePath); File sourceFile2 = new File(filePath); entity.addPart("images[0]", new FileBody(sourceFile)); entity.addPart("images[1]", new FileBody(sourceFile2)); //Do your stuff multiple files entity.addPart("file_type", new StringBody("image"); entity.addPart("file_form", new StringBody("post"); httppost.addHeader("Accept","application/json"); httppost.addHeader("Content-Type", "multipart/form-data"); httppost.addHeader("Authorization", "Bearer " + sharedPreferencesManager.retreiveString(AppText.ACCESS_TOKEN)); httppost.setEntity(entity); // Making server call HttpResponse response = httpclient.execute(httppost); HttpEntity r_entity = response.getEntity(); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { // Server response statusCode = 200; responseString = EntityUtils.toString(r_entity); } else { statusCode = 200; responseString = "Error occurred! Http Status Code: " + statusCode; } } catch (ClientProtocolException e) { responseString = e.toString(); } catch (IOException e) { responseString = e.toString(); } return responseString; } @Override protected void onPostExecute(String result) { hideProgressDialog(); }
}
5.Calling异步
new registerCall().execute();