1

I have a C/S application. I implemented the server with Asp.Net MVC 4.0, and the client runs on .Net 4.5.

I have a Controller Action in the server side looks like this:

public JsonResult Upload(string arg1, int arg2)
{
    //do something about arg1 and arg2 here
    ...

    var files = Request.Files;
    if (files.Count > 0)
    {
        foreach(var file in files)
        {
            var ms = new MemoryStream();
            file.InputStream.CopyTo(ms);
            //save it to somewhere
            ...
        }
    }

    ...
}

I created a test html page to test it in browser. It worked as expected.

In the client side, I use HttpClient class and it worked perfectly where no file uploading involved. However after days of researching I still have no luck to resolve this in my debug machine which runs IIS Express. I found that all clues leads to MultipartFormDataContent, but still can't get it work, even if I copy those sample codes, the server side still can't get a thing, all args are empty, and no files is there in the Request.Files. I used to have my own http helper class based on HttpWebRequest, which works for file uploading, but I prefer to use HttpClient in this new project.

So, How do I upload files to the server with HttpClient?

1
  • Note that I did not test this in IIS, nor did I test it with Asp.net MVC 3.0. Commented Mar 26, 2013 at 13:46

1 Answer 1

3

After debugging with Fiddler, comparing raw http message with WinMerge, I found the differences between Firefox and my program:

Firefox (removed some headers to make things simpe):

POST http://localhost:53400/Input/Upload HTTP/1.1
Host: localhost:53400
Content-Type: multipart/form-data; boundary=---------------------------1590871622043
Content-Length: ****

-----------------------------1590871622043
Content-Disposition: form-data; name="arg1"

abc
-----------------------------1590871622043
Content-Disposition: form-data; name="arg2"

3
-----------------------------1590871622043
Content-Disposition: form-data; name="uploadfile"; filename="wave.wav"
Content-Type: audio/wav

//file data here
-----------------------------1590871622043--

My Program with MultipartFormDataContent:

POST http://localhost:53400/Input/Save HTTP/1.1
Content-Type: multipart/form-data; boundary="caac5ea7-8ab4-4682-be40-ecb3ddf3e70a"
Host: localhost:53400
Content-Length: ****

--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=arg1

abc
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=arg2

3
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=uploadfile; filename=wave.wav; filename*=utf-8''wave.wav

//file data here
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a--

The last thing I would notice is that in these Content-Disposition lines, Firefox quotes all values, but my program does not. One could easily assume that it would not matter, but in the end, I found that is the exact cause.

Now that I know the reason, here comes the code that works, as easy as quoting the names:

var multipart = new MultipartFormDataContent();
multipart.Add(new StringContent("abc"), '"' + "arg1" + '"');
multipart.Add(new StringContent("3"), '"' + "arg2" + '"');

// byte[] fileData;
multipart.Add(new ByteArrayContent(fileData), '"' + "uploadfile"+ '"', '"' + "wave.wav" + '"');
//HttpClient http; string url;
var response = await http.PostAsync(url, multipart);
response.EnsureSuccessStatusCode();
//...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.