Mark Micallef
Mark Micallef

Reputation: 2788

AJAX: Asynchronously posting a file to a server

I want to post a file to server asynchronously without posting the form. I have the following code:

var fileInput = document.getElementById('FileInput');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('file', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://servername/controllername/AnalyseFile', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(formData);

However, when the method is executed on the server, the post body contains no files. The following is from ASP.NET MVC4:

[HttpPost]
public JsonResult AnalyseFile()
{
  int filesCount = Request.Files.Count;
  if(filesCount == 0) { throw new Exception('no files...'); }
  // do stuff
}

The Files collection contains no files and I can't figure out why. Any help appreciated.

Upvotes: 0

Views: 388

Answers (2)

Jonathan
Jonathan

Reputation: 1027

In the View, you can do:

<form>
<input name="input1" id="input1"/>
<input name="input2" id="input2"/>
<input name="input3" id="input3"/>
...
<input id="SelectedFile" name="SelectedFile" type="file"/>
</form>

And Javascript:

function AttLogic(_url, _data, _callback) {
    $.ajax({
        url: _url,
        type: 'POST',
        xhr: function () {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) { }
            return myXhr;
        },
        data: _data,
        cache: !1,
        success: _callback,
        contentType: !1,
        processData: !1
    });
}

function FormDataCustom(f) {
    var __frm = jQuery(f), data = new FormData(f);
    $(':disabled[name]', __frm).each(function () {
        data.append(this.name, $(this).val());
    });
    return data;
}

function SaveLogic(){
var dt = FormDataCustom(document.forms[0]);
AttLogic(yourUrl, dt, function (r) {
        //do something here
    });
}

In the Controller:

public ActionResult Save(parameter1,parameter1,..., List<HttpPostedFileBase> SelectedFile)
{
    //do something here
}

Upvotes: 1

JanR
JanR

Reputation: 6132

You will need to read the MultiPartFormData from the Request.

As per this post:

Your method will look something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace Some.Namespace
{
    public class SomeController : ApiController
    {
        [HttpPost]
        public async Task<JsonResult> AnalyseFile()
        {
             if (!Request.Content.IsMimeMultipartContent())
             {
                 //If not throw an error
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
             }

             MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider("c:\\tmp\\uploads");

            // Read the MIME multipart content using the stream provider we just created.
            IEnumerable<HttpContent> bodyparts = await  Request.Content.ReadAsMultipartAsync(streamProvider);

            // Get a dictionary of local file names from stream provider.
            // The filename parameters provided in Content-Disposition header fields are the keys.
            // The local file names where the files are stored are the values.
            //depending on your version of .net, this might have been changed to FileData instead. 
            // see: https://msdn.microsoft.com/en-us/library/system.net.http.multipartformdatastreamprovider(v=vs.118).aspx
            IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;

            //rest of code here

    }
}

I haven't tested the above code, but it should point you in the right direction.

Also have a look at How To Accept a File POST

For a more recent article: https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e

Upvotes: 0

Related Questions