1

I have a simple form which contains a input of type file which accepts only images. I just want to post the file save it in table as well as 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 the Request.Files.Count it will always be zero. Is there any alternate workaround or am I doing any mistakes in posting the file. I have followed this link and have made changes according to my needs.

6
  • 1
    For starters you're passing a formData object to the ajax call, then you're stringifying it, which won't work, why would you send a string of JSON when you're trying to send files? Secondly, you have to set certain options in the ajax call, data prossessing has to be turned off etc. and a quick search will give you hundreds of answers with example code of what to set for the ajax call to make it work properly. Commented Mar 7, 2015 at 16:38
  • @adeneo.. I have updated the question... Still the result is same. Commented Mar 7, 2015 at 16:52
  • Now look at msg, it's defined in a totally different function, which by the way is asynchronous Commented Mar 7, 2015 at 16:57
  • that msg is global and is jus for my reference to display valid or invalid message to user. How is that related to retrieve Request.Files in controller method Commented Mar 7, 2015 at 17:01
  • 1
    I just noted that it wouldn't work, even if it's global, as postData is async. That shouldn't stop the files from being sent though, unfortunately my ASP isn't very good, but it looks like you're expecting JSON, but that's not what you're sending now, after you changed the ajax options you're now sending a standard www-encoded form. Commented Mar 7, 2015 at 17:05

1 Answer 1

4

Instead of:

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

you might 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 doesn't contain a filename and thus ASP.NET doesn't recognize it as a 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 will 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--

Now you can see the actual difference. In the first case you don't have a filename nor Content-Type of the files and ASP.NET simply treat those elements as standard form posted data and not files.

Also instead of using the actual file name as name you may consider replacing it with some generic one:

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

Now you can further improve your controller action by having it take a List<HttpPostedFileBase> parameter instead of using Request.Files:

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

Another remark about your code is that HTML5 FormData is not available in order browsers and your code will silently fail. If you need to support older browsers you might need to perform progressive enhancement by testing the capabilities of the browser and falling back to a standard form POST 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();

        ...
    }
});
Sign up to request clarification or add additional context in comments.

5 Comments

its not problem with appending. Appending is happening properly but formData will not be received in controller part..
No, it's a problem with appending, believe me. Did you try my suggestion? I am now elaborating my answer to be more clear why your approach is problematic.
Am sorry bro. This is perfect. Sorry for commenting without trying it out.. Your explaination helped.. :)
Now if I want to add extra data to formData like textbox value, how can I achieve it. just post it as comment. don't edit your answer..
Well: formdata.append('nameOfYourInputElement', 'Value of the input element');. Obviously you could automate this by looping through all your form input elements instead of manually doing it for each separate element.

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.