Uploading file via ajax doesn't add file to request in MVC

I have a simple form that contains an input file of type that only accepts images. I just want to post a file to save it in a table as well as on the server.

Below is my cshtml

@using (Html.BeginForm("UploadSlider", "Admin", FormMethod.Post, new { id = "frmUploadSliderImage", @class = "form-admin" }))
{
     <h2 class="form-login-heading">upload images</h2>
     <div class="login-wrap">
     <span class="btn btn-default btn-file">
     Browse <input type="file" id="sliderFile" multiple="multiple">
     </span>&nbsp;
     <span class="text-muted" id="filePlaceHolder">No files selected</span>
     <span class="text-danger"></span>
     <button class="btn btn-theme btn-block" name="upload" onclick="javascript: ValidateSliderImageandPost('frmUploadSliderImage', this);" id="btnUploadSliderImage" type="submit"><i class="fa fa-upload"></i> UPLOAD</button>
     </div>
}

      

this is my js ajax part

function ValidateSliderImageandPost(form, ctrl) {
    $("#" + form).on("submit", function (e) {
        e.preventDefault();
        var formContainer = $('#' + form + ' .text-danger');
        var formdata = new FormData();
        var fileInput = $('#sliderFile');
        if ($(fileInput).get(0).files.length == 0)
        {
            $('.btn-file :file').parent().siblings().filter(".text-danger").html('Please select a file!');
        }
        if ($(formContainer).text().length == 0) {
            run_waitMe('Uploading! Please wait...', 'stretch', '.container');
            $.each($(fileInput).get(0).files, function (index,value) {
                formdata.append($(this).attr('name'), $(this));
            });
            postData('UploadSlider', formdata, '.upslider .status');
            if (msg) {
                $(".container").find('#cont').waitMe('hide');
                $("#" + form).find('input[type=text], textarea').val('').removeClass("alert-success");
            }
            else {
                $(".container").find('#cont').waitMe('hide');
                $("#" + form).find('input[type=text], textarea').removeClass("alert-success");
            }

        }
        $("#" + form).unbind('submit');
        return false;
    });
}

function postData(url,data,target)
{
$.ajax({
    url: url,
    type: "POST",
    dataType: 'json',
    data: data,
    processData: false,
    contentType:false,
    success: function (data) {
        if (data.result) {
            animateStatus("success", data.message, target);
            msg = true;
        }
        else {
            animateStatus("fail", data.message, target);
            msg = false;
        }
    },
    error:
        function (data) {
            animateStatus("fail", data.message, target);
            msg = false;
        }
});
}

      

This is my controller part

[HttpPost]
        public JsonResult UploadSlider()
        {
            bool valid = false;
            bool val = false;
            if (Request.Files.Count > 0)
            {
                valid = true;
            }
            else
            {
                return Json(new { result = false, message = "Something went wrong! Please try again!" });
            }
            if (valid)
            {
                List<string> fil = new List<string>();
                foreach (HttpPostedFileBase f in Request.Files)
                {
                    HttpPostedFileBase file = f; //Uploaded file
                    string fileName = file.FileName;
                    fil.Add("./Images/Galllery/" + fileName);
                    System.IO.Stream fileContent = file.InputStream;
                    file.SaveAs(Server.MapPath("~/Images/Gallery/") + fileName);
                }
                using (var context = new MCBConnectionString())
                {
                    foreach (string path in fil)
                    {
                        tbl_slider slider = new tbl_slider();
                        slider.slurl = path;
                        slider.slalt = "";
                        context.tbl_slider.Add(slider);
                        context.SaveChanges();
                        val = true;
                    }
                }
                if (val)
                {
                    return Json(new { result = true, message = "Uploaded video successfully." });
                }
                else
                {
                    return Json(new { result = false, message = "Could not upload video. Please try again!" });
                }
            }
            return Json(new { result = false, message = "Could not upload video. Please try again!" });


        }

      

When I debug and check Request.Files.Count it will always be zero. Is there an alternative workaround or am I making any mistakes when uploading the file. I followed this one and made changes to suit my needs.

+1


source to share


1 answer


Instead:

$.each($(fileInput).get(0).files, function (index, value) {
    formdata.append($(this).attr('name'), $(this));
});

      

you can use:

$.each($(fileInput).get(0).files, function (index, value) {
    formdata.append(value.name, value);
});

      

The main difference is that with your approach, the Content-Disposition part does not contain filename

, and therefore ASP.NET does not recognize it as file content:

------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="foo.png"

[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="bar.png"

[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO--

      

and with my approach the request would look like this:

------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="foo.png"; filename="foo.png"
Content-Type: imag/png

[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="bar.png"; filename="bar.png"
Content-Type: image/png

[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0--

      



You can now see the actual difference. In the first case, you have no files filename

and Content-Type

, and ASP.NET simply treats these elements as standard form data, not files.

Instead of using the actual filename as name

, you might consider replacing it with something generic:

$.each($(fileInput).get(0).files, function (index, value) {
    formdata.append('sliderFiles', value);
});

      

You can now further improve your controller action by Request.Files

using a parameter instead List<HttpPostedFileBase>

:

[HttpPost]
public ActionResult UploadSlider(List<HttpPostedFileBase> sliderFiles)
{
    ...
}

      

One more note about your code: HTML5 is FormData

not available for browsers and your code will fail. If you need to support older browsers, you might need to progressively boost by checking the browser capabilities and falling back to a standard POST form if the browser doesn't support FormData:

$("#" + form).on("submit", function (e) {
    if(window.FormData === undefined) {
        // The browser doesn't support uploading files with AJAX
        // falling back to standard form upload
    } else {
        // The browser supports uploading files with AJAX =>
        // we prevent the default form POST and use AJAX instead
        e.preventDefault();

        ...
    }
});

      

+3


source







All Articles