3

I am trying to send multipart data to a server, this data includes also some images. So i extended Request in this way:

public class MultipartImageRequest extends Request<String> {

private MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();

private static final String STRING_PART_NAME = "text";

private final Response.Listener<String> mListener;
private final ArrayList<Bitmap> mFiles = new ArrayList<>();
private HashMap<String, String> mParams = new HashMap<>();

public MultipartImageRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, ArrayList<Bitmap> files, HashMap<String, String> params)
{
    super(Method.POST, url, errorListener);

    mListener = listener;
    mFiles.addAll(files);
    mParams = params;

}

private void buildMultipartEntity()
{

    int i = 0;
    for(Bitmap image : mFiles) {

        /*Compress bitmap*/
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 50, bos);

        entityBuilder.addPart("image_" + i, new ByteArrayBody(bos.toByteArray(), "image_" + i));
        i++;

    }


    StringBuilder paramsBuilder = new StringBuilder();
    Iterator<Map.Entry<String, String>> paramIterator = mParams.entrySet().iterator();
    while (paramIterator.hasNext()) {

        Map.Entry<String,String> entry = paramIterator.next();
       entityBuilder.addPart(entry.getKey(), new StringBody(entry.getValue(), ContentType.DEFAULT_TEXT));

    }




}

@Override
public String getBodyContentType()
{
    return "multipart/form-data; charset=utf-8";
}

@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();
}

@Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
    return Response.success("Uploaded", getCacheEntry());
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String,String> params = new HashMap<String, String>();
    params.put("Content-Type","multipart/form-data; charset=utf-8");
    return params;
}

@Override
protected void deliverResponse(String response)
{
    mListener.onResponse(response);
}
}

The problem is that if i set as a content type application/json it works and sends data to the server, but obviously the server gives me back an error 400 because it is expecting a multipart request, rather if i set the content type as multipart/form-data; charset=utf-8 like in the code above Volley just doesn't send the request and gives me an error 500. I am using RequestBin to check my data and it confirms what i said above. Also i am using a Rest Client and the request is working with it and on iphone too.

MineConsulting SRL
  • 2,340
  • 2
  • 17
  • 32

1 Answers1

1

I found the solution on my own, it is important to pass a boundary to the request, otherwise the server will not be able to take our parameters. It can be done replacing this code:

public MultipartImageRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, ArrayList<Bitmap> files, HashMap<String, String> params)
{
    super(Method.POST, url, errorListener);

    mListener = listener;
    mFiles.addAll(files);
    mParams = params;

}

with this one:

public MultipartImageRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, ArrayList<Bitmap> files, HashMap<String, String> params)
{
    super(Method.POST, url, errorListener);

    mListener = listener;
    mFiles.addAll(files);
    mParams = params;
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    entityBuilder.setBoundary(BOUNDARY);
}

and remember to set the boundary string in your Content-Type:

@Override
public String getBodyContentType()
{
    return "multipart/form-data; boundary=" + BOUNDARY + "; charset=utf-8";
}


@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String,String> params = new HashMap<String, String>();

    params.put("Content-Type","multipart/form-data; boundary=" + BOUNDARY + "; charset=utf-8");
    return params;
}
MineConsulting SRL
  • 2,340
  • 2
  • 17
  • 32