I have a customers HTTP call working using the standard apache classes but I am trying to create a custom Volley class to handle this. Here is the code for standard call:
HttpURLConnection conn = (HttpURLConnection) new URL(strUrl).openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(30000);
conn.setUseCaches(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Token " + m_apiKey);
conn.setRequestProperty("Accept", "text/plain , application/json");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + strBoundary);
conn.connect();
// **** Start content wrapper:
DataOutputStream request = new DataOutputStream(conn.getOutputStream());
request.writeBytes("\r\n--" + strBoundary + "\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"" + attachmentName + "\";filename=\"" + imageFileName + "\"" + "\r\n");
request.writeBytes("Content-Type: image/jpeg " + "\r\n");
request.writeBytes("\r\n");
request.write(baos.toByteArray());
// **** End content wrapper:
request.writeBytes("\r\n--"+ strBoundary + "--\r\n");
// Flush output buffer:
request.flush();request.close();
Not sure how to do the rest but this is what I have for the Volley that is not working. I've done Multipart before but not with boundary and in this weird format.
public class ImageMultiRequest extends StringRequest { final String BOUNDARY = "something"; final String crlf = "\r\n"; final String twoHyphens = "--";
private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
private Response.Listener<String> mListener = null;
private Response.ErrorListener mEListener;
//
private final File mFilePart;
private Map<String, String> parameters;
private Map<String, String> header;
MultipartEntity entity = new MultipartEntity();
protected String apiKey;
ByteArrayOutputStream bos;
public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) {
super(Method.POST, url, rListener, eListener);
setShouldCache(false);
this.apiKey = apiKey;
this.bos = bos;
mListener = rListener;
mEListener = eListener;
mFilePart = file;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(BOUNDARY);
buildMultipartEntity();
}
@Override
public String getBodyContentType() {
return "multipart/form-data; boundary=" + BOUNDARY + "; charset=utf-8";
}
/**
* Overrides the base class to add the Accept: application/json header
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8");
headers.put("Connection", "Keep-Alive");
headers.put("Accept", "text/plain , application/json");
headers.put("Authorization", "Token " + apiKey);
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
buildMultipartEntity();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
entityBuilder.build().writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
private void buildMultipartEntity() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
entityBuilder.addPart("Content-Type: image/jpeg " + crlf + crlf, new ByteArrayBody(bos.toByteArray(), "car"));
}
}
=================================================
Here is what I came up with that worked for this and possibly other problems with multipart file embedded the Content Body
package com.cars.android.common.volley;
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.StringRequest;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ImageMultiRequest extends StringRequest {
final String BOUNDARY = "myboundary";
private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
HttpEntity entity = new MultipartEntity();
private Response.Listener<String> mListener = null;
private Response.ErrorListener mEListener;
//
private final File mFilePart;
protected String apiKey;
public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) {
super(Method.POST, url, rListener, eListener);
setShouldCache(false);
this.apiKey = apiKey;
mListener = rListener;
mEListener = eListener;
mFilePart = file;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(BOUNDARY);
ContentType contentType = ContentType.create("image/png");
entityBuilder.addBinaryBody("file", file, contentType, "car");
entity = entityBuilder.build();
}
@Override
public String getBodyContentType() {
return entity.getContentType().getValue();
}
/**
* Overrides the base class to add the Accept: application/json header
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8");
headers.put("Connection", "Keep-Alive");
headers.put("Accept", "text/plain , application/json");
headers.put("Authorization", "Token " + apiKey);
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
entity.writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
}
This is my working sample code (only tested with small-size files):
public class FileUploadActivity extends Activity {
private final Context mContext = this;
HttpEntity httpEntity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_upload);
Drawable drawable = getResources().getDrawable(R.drawable.ic_action_home);
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
final byte[] bitmapdata = stream.toByteArray();
String url = "http://10.0.2.2/api/fileupload";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// Add binary body
if (bitmapdata != null) {
ContentType contentType = ContentType.create("image/png");
String fileName = "ic_action_home.png";
builder.addBinaryBody("file", bitmapdata, contentType, fileName);
httpEntity = builder.build();
MyRequest myRequest = new MyRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
Toast.makeText(mContext, jsonString, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mContext, error.toString(), Toast.LENGTH_SHORT).show();
}
}) {
@Override
public String getBodyContentType() {
return httpEntity.getContentType().getValue();
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
httpEntity.writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
};
MySingleton.getInstance(this).addToRequestQueue(myRequest);
}
}
}
...
}
public class MyRequest extends Request<NetworkResponse>