Reputation: 1848
I'm just beginner in Android App development.
I want to upload image files using Android Volley library.
I have used this helper class found somewhere in some blog.:
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;
}
}
}
And called this helper like this:
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;
}
};
I'm getting server error as a response.
I tried different tutorials but didn't find the exact way and easy solution.
In the postman, headers and params are like this, there are an array of images, you can see in photos attached (8 photos). I want to do exact same API call using volley library.
Upvotes: 1
Views: 4221
Reputation: 20
Just replace getByteData() method with this below code:
private dataPartList = ArrayList();
@Override
protected Map<String, List<DataPart>> getByteDataList(){
Map<String, List<DataPart>> params = new HashMap<>();
params.put("yourKey","dataPartList");
return params
}
Upvotes: -1
Reputation: 3539
Try this code:
I had similar kind of issue i fixed using this
Uploading multiple files in array
using multipart
Add dependecies
compile 'org.apache.httpcomponents:httpcore:4.2.4'
compile 'org.apache.httpcomponents:httpmime:4.2'
compile 'com.mcxiaoke.volley:library:1.0.19'
2.Add in gradle
defaultConfig {
useLibrary 'org.apache.http.legacy'
}
Helper class 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 call method
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 Async
new registerCall().execute();
Upvotes: 4