通过ajax上传文件不会在MVC中的请求中附加文件 [英] File upload through ajax does not append file in Request in MVC

查看:21
本文介绍了通过ajax上传文件不会在MVC中的请求中附加文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的表单,其中包含一个只接受图像的文件类型的输入.我只想发布文件,将其保存在表和服务器中.

下面是我的cshtml

@using (Html.BeginForm("UploadSlider", "Admin", FormMethod.Post, new { id = "frmUploadSliderImage", @class = "form-admin" })){<h2 class="form-login-heading">上传图片</h2><div class="login-wrap"><span class="btn btn-default btn-file">浏览<input type="file" id="sliderFile" multiple="multiple"></span>&nbsp;<span class="text-muted" id="filePlaceHolder">未选择任何文件</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>上传

}

这是我的 js ajax 部分

function ValidateSliderImageandPost(form, ctrl) {$("#" + form).on("submit", function (e) {e.preventDefault();var formContainer = $('#' + form + '.text-danger');var formdata = new FormData();var fileInput = $('#sliderFile');如果 ($(fileInput).get(0).files.length == 0){$('.btn-file :file').parent().siblings().filter(".text-danger").html('请选择一个文件!');}如果 ($(formContainer).text().length == 0) {run_waitMe('上传中!请稍等...', 'stretch', '.container');$.each($(fileInput).get(0).files, function (index,value) {formdata.append($(this).attr('name'), $(this));});postData('UploadSlider', formdata, '.upslider .status');如果(味精){$(".container").find('#cont').waitMe('hide');$("#" + form).find('input[type=text], textarea').val('').removeClass("alert-success");}别的 {$(".container").find('#cont').waitMe('hide');$("#" + form).find('input[type=text], textarea').removeClass("alert-success");}}$("#" + form).unbind('submit');返回假;});}函数 postData(url,data,target){$.ajax({网址:网址,类型:POST",数据类型:'json',数据:数据,过程数据:假,内容类型:假,成功:功能(数据){如果(数据.结果){animateStatus("success", data.message, target);味精=真;}别的 {animateStatus("fail", data.message, target);味精=假;}},错误:功能(数据){animateStatus("fail", data.message, target);味精=假;}});}

这是我的控制器部分

[HttpPost]公共 JsonResult UploadSlider(){布尔有效 = 假;布尔值 = 假;如果(Request.Files.Count > 0){有效 = 真;}别的{return Json(new { result = false, message = "出现问题!请再试一次!" });}如果(有效){列表<字符串>fil = new List();foreach(Request.Files 中的 HttpPostedFileBase f){HttpPostedFileBase 文件 = f;//上传的文件字符串文件名 = 文件.文件名;fil.Add("./Images/Gallery/" + 文件名);System.IO.Stream fileContent = file.InputStream;file.SaveAs(Server.MapPath("~/Images/Gallery/") + fileName);}使用 (var context = new MCBConnectionString()){foreach(fil 中的字符串路径){tbl_slider 滑块 = 新 tbl_slider();滑块.slurl = 路径;滑块.salt = "";context.tbl_slider.Add(slider);context.SaveChanges();val = 真;}}如果(值){return Json(new { result = true, message = "视频上传成功." });}别的{return Json(new { result = false, message = "无法上传视频,请重试!" });}}return Json(new { result = false, message = "无法上传视频,请重试!" });}

当我调试并检查 Request.Files.Count 时,它将始终为零.是否有任何替代解决方法,或者我在发布文件时是否犯了任何错误.我关注了this 链接并根据我的需要进行了更改.

解决方案

代替:

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

你可能会使用:

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

主要区别在于,使用您的方法,Content-Disposition 部分不包含 filename,因此 ASP.NET 不会将其识别为文件内容:

------WebKitFormBoundaryZxwCwBC0O8Q3hOAO内容配置:表单数据;名称=foo.png"[对象对象]------WebKitFormBoundaryZxwCwBC0O8Q3hOAO内容配置:表单数据;名称=bar.png"[对象对象]------WebKitFormBoundaryZxwCwBC0O8Q3hOAO--

按照我的方法,请求将如下所示:

------WebKitFormBoundary1ERBVX0wzdVczcR0内容配置:表单数据;名称="foo.png";文件名=foo.png"内容类型:图像/PNG[对象对象]------WebKitFormBoundary1ERBVX0wzdVczcR0内容配置:表单数据;名称="bar.png";文件名=bar.png"内容类型:图像/png[对象对象]------WebKitFormBoundary1ERBVX0wzdVczcR0--

现在您可以看到实际差异了.在第一种情况下,您没有文件的 filenameContent-Type,ASP.NET 只是将这些元素视为标准表单发布的数据而不是文件.

此外,您可以考虑将其替换为一些通用文件名,而不是使用实际文件名作为 name:

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

现在您可以通过使用 List 参数而不是使用 Request.Files 来进一步改进控制器操作:

[HttpPost]public ActionResult UploadSlider(ListsliderFiles){...}

关于您的代码的另一个评论是 HTML5 FormData 在订单浏览器中不可用,您的代码将无声无息地失败.如果您需要支持较旧的浏览器,您可能需要通过测试浏览器的功能来执行渐进式增强,如果浏览器不支持 FormData,则回退到标准表单 POST:

$("#" + form).on("submit", function (e) {if(window.FormData === 未定义) {//浏览器不支持 AJAX 上传文件//回退到标准表单上传} 别的 {//浏览器支持使用 AJAX => 上传文件//我们阻止默认表单 POST 并使用 AJAX 代替e.preventDefault();...}});

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.

解决方案

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();

        ...
    }
});

这篇关于通过ajax上传文件不会在MVC中的请求中附加文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆