2

I'm using any one of several examples found all over the place to do a file upload with .net Web API. The files get stored to the server, but the fileData object on the provider always returns empty. Code below.

 var url = "api/Documents/fileUpload";
                    var xhr = new XMLHttpRequest();
                    var file = document.getElementById("inputFile").files[0];
                    var formData = new FormData();
                    formData.append('file', file);
                    xhr.open("POST", url, true);
                    xhr.responseType = "text";
                    xhr.onreadystatechange = function () {
                        if (xhr.readyState == xhr.DONE) {
                            console.log("photoUpload xhr", xhr);
                            var responseTypeAsJSON = JSON.parse(xhr.responseText);
                            currentPhoto.responseText = xhr.responseText;
                            if (responseTypeAsJSON.result == "SUCCESS") {
                                currentPhoto.status = "SUCCESSfully uploaded";
                            }
                            else {
                                currentPhoto.status = responseTypeAsJSON.result;
                                alert(responseTypeAsJSON.message);
                            }
                            PhotoClear();
                            // console.log(currentPhoto);
                            // console.log("xhr done: ", xhr);  

                        }
                    }
                    xhr.send(formData);
                    // console.log("xhr sent: ", xhr);

CONTROLLER TO RECEIVE:

      [HttpPost]
    [ActionName("fileUpload")]
    public Task<HttpResponseMessage> fileUpload()
    {
        HttpRequestMessage request = this.Request;
        if (!request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        var task = request.Content.ReadAsMultipartAsync(provider).
            ContinueWith<HttpResponseMessage>(o =>
            {

                string file1 = provider.FileData.First().LocalFileName.ToString();
                // this is the file name on the server where the file was saved 

                return new HttpResponseMessage()
                {
                    Content = new StringContent("File uploaded.")
                };
            }
        );
        return task;
    }

Here is the request from Chrome. When I debug the provider, the keys of the form data are empty as well. Yet the file gets put into the AppData

Request URL:http://localhost:4231/api/Documents/fileUpload
Request Headersview source
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarycuGegdEDmBsR0mMl
Origin:http://localhost:4231
Referer:http://localhost:4231/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko)     Chrome/25.0.1364.172 Safari/537.22
Request Payload
------WebKitFormBoundarycuGegdEDmBsR0mMl
Content-Disposition: form-data; name="testInfo"

some info here for testing
------WebKitFormBoundarycuGegdEDmBsR0mMl
Content-Disposition: form-data; name="file"; filename="irislogo.png"
Content-Type: image/png


------WebKitFormBoundarycuGegdEDmBsR0mMl--
6
  • hmm..looking at the action above, there should not be any problem in getting the filename...i know this doesn't matter since you are seeing the file getting created, but could you share how your raw request looks like so that i could try to repro it.. Commented Mar 18, 2013 at 19:39
  • Thanks for the request details. I am unable to repro it using the above request details and the action. I am able to see the value for the local file name property. Commented Mar 18, 2013 at 20:25
  • It's the oddest thing. File makes it to the directory, but the task portion with the Read..Async never gets executed since the formdata always appears empty. Commented Mar 18, 2013 at 20:29
  • ah, try the following in the continuewith: var formProvider = o.Result; string file1 = formProvider.FileData.First().LocalFileName.ToString(); Commented Mar 18, 2013 at 20:36
  • With a break point set at file1, never gets hit. Commented Mar 18, 2013 at 20:53

2 Answers 2

3

I was running into this exact issue and a small code change fixed the issue.

The line:

 var provider = new MultipartFormDataStreamProvider(root);

Should be:

 var provider = new MultipartFileStreamProvider(root);
Sign up to request clarification or add additional context in comments.

2 Comments

This solved the issue for me. But I don't understand why? I send the data as FormData, shouldn't it still be FormData and not a File?
Under the hood, .Net has logic to separate the files from the FormData during model binding. This was introduced in WebAPI 2 so you can override the file handling logic to do things like upload directly to Azure Blob storage. For a deeper understanding refer to the WebAPI lifecycle, specifically model binding: asp.net/media/4071077/aspnet-web-api-poster.pdf
1

I also had this issue; here is the solution:

public async Task<HttpResponseMessage> Save()
{
    string root = HttpContext.Current.Server.MapPath("~/App_Data");

    var provider = new MultipartFormDataStreamProvider(root);

    await Request.Content.ReadAsMultipartAsync(provider);

    // provider.FileData will contain your data...
    // you can also send form data which will be in provider.FormData
}

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.