【问题标题】:File upload through ajax does not append file in Request in MVC通过ajax上传文件不会在MVC中的Request中附加文件
【发布时间】:2015-05-09 03:16:44
【问题描述】:

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

下面是我的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>
}

这是我的 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');
        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;
        }
});
}

这是我的控制器部分

[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!" });


        }

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

【问题讨论】:

  • 对于初学者来说,您将 formData 对象传递给 ajax 调用,然后将其字符串化,这是行不通的,为什么在尝试发送时要发送 JSON 字符串文件?其次,您必须在 ajax 调用中设置某些选项,必须关闭数据处理等。快速搜索将为您提供数百个答案,其中包含为 ajax 调用设置什么以使其正常工作的示例代码。
  • @adeneo.. 我已经更新了问题... 结果还是一样。
  • 现在看看msg,它是在一个完全不同的函数中定义的,顺便说一下是异步的
  • msg 是全局的,仅供我参考,用于向用户显示有效或无效的消息。这与在控制器方法中检索 Request.Files 有什么关系
  • 我只是注意到它不起作用,即使它是全局的,因为 postData 是异步的。这不应该阻止文件被发送,不幸的是我的 ASP 不是很好,但看起来你期待 JSON,但这不是你现在发送的,在你改变了你的 ajax 选项之后现在发送一个标准的 www 编码形式。

标签: javascript jquery ajax asp.net-mvc file-upload


【解决方案1】:

代替:

$.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
Content-Disposition: form-data; name="foo.png"

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

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

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

------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--

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

除了使用实际文件名name,您还可以考虑将其替换为一些通用名称:

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

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

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

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

$("#" + 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();

        ...
    }
});

【讨论】:

  • 追加没有问题。附加操作正常,但控制器部分不会收到 formData..
  • 不,这是附加的问题,相信我。你试过我的建议了吗?我现在正在详细说明我的答案,以便更清楚地说明您的方法存在问题的原因。
  • 对不起兄弟。太棒了。很抱歉没有尝试就发表评论..您的解释有帮助.. :)
  • 现在,如果我想向 formData 添加额外的数据,如文本框值,我该如何实现。只需将其发布为评论。不要编辑你的答案..
  • 好吧:formdata.append('nameOfYourInputElement', 'Value of the input element');。显然,您可以通过循环遍历所有表单输入元素来自动执行此操作,而不是手动为每个单独的元素执行此操作。
猜你喜欢
  • 2021-12-10
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多