0

I'm trying to upload a picture from my android app to a web api project on my IIS Server. First, on the Android Side, I made the following custom volley request:

public class PictureRequest extends Request<NetworkResponse> {


private String mMimeType;
private byte[] mMultipartBody;
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;

public PictureRequest(String url, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
    super(Method.POST, (ApplicationController.getInstance().getWS_BASE_URI() + url), errorListener);
    this.mMimeType = mimeType;
    this.mMultipartBody = multipartBody;
    this.mListener = listener;
    this.mErrorListener = errorListener;
}

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


@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
public void deliverError(VolleyError error) {
    mErrorListener.onErrorResponse(error);
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> headers = new HashMap<String, String>();
    String auth = "Basic " + Base64.encodeToString((ApplicationController.getInstance().getWS_KEY()+":").getBytes(),
                    Base64.NO_WRAP);
    headers.put("Authorization", auth);
    return headers;
}

@Override
public String getBodyContentType() {
    return mMimeType;
}

@Override
public byte[] getBody() throws AuthFailureError {
    return mMultipartBody;
}

The following codewhows how I build the multipart:

private void buildPart(DataOutputStream dataOutputStream, byte[] fileData, String fileName) throws IOException 
{
    dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
    dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\"; filename=\""
            + fileName + "\"" + lineEnd);
    dataOutputStream.writeBytes("Content-Type: image/png" + lineEnd);
    dataOutputStream.writeBytes(lineEnd);

    ByteArrayInputStream fileInputStream = new ByteArrayInputStream(fileData);
    int bytesAvailable = fileInputStream.available();

    int maxBufferSize = 1024 * 1024;
    int bufferSize = Math.min(bytesAvailable, maxBufferSize);
    byte[] buffer = new byte[bufferSize];

    // read file and write it into form...
    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);
}

The MIMEType is buils as follows:

long boundary = System.currentTimeMillis();
String mimeType = "multipart/form-data;boundary=" + boundary;

On the server side, on the controller under the adress Profil/UpdatePicture I have the following method that catch the multidata form request:

[HttpPost]
    [Route("api/Profil/UpdatePicture")]
    public async Task<HttpResponseMessage> UpdatePicture()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        string root = HttpContext.Current.Server.MapPath("~/Data/IN/ProfilPictures");
        var provider = new CustomMultipartFormDataStreamProvider(root);

        var task = await Request.Content.ReadAsMultipartAsync(provider).
            ContinueWith<HttpResponseMessage>(t =>
            {
                if (t.IsFaulted || t.IsCanceled)
                {
                    Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
                }
                return Request.CreateResponse(HttpStatusCode.OK);
            });

        return task;
    }

As you can see, i've used a custom MultipartFormStreamProvider in order to make a custom file name pattern.

When I'm trying to upload a picture from an HTML form on the web api UI, the upload succeded. But when I'm uploading from my Android App using the above volley request, even if I get a 200 Http code in return, the picture is not uploaded... The IIS server has total control on the targeted folders where the picture have to be uploaded. It's been two days that I'm dealing with that issue... Does somebody sees where is the problem ?

Hubert Solecki
  • 2,611
  • 5
  • 31
  • 63
  • 1
    Pls post more code at the activity how did you call your request. Moreover, have you read my following question http://stackoverflow.com/questions/32240177/working-post-multipart-request-with-volley-and-without-httpentity yet? – BNK Dec 30 '15 at 00:12
  • 1
    Hey, thank you ! Actually yes, my code was based on your question by I've done something wrong while adapted. I'll answer to my question in a while, redirecting directly to your question ! Great ! You could write an article about it as many people would search for that ;) @BNK – Hubert Solecki Dec 30 '15 at 07:22
  • Another option is using `OkHttp`, please take a look at my github link https://github.com/ngocchung/multipartokhttp :) – BNK Dec 30 '15 at 07:25

0 Answers0