代码之家  ›  专栏  ›  技术社区  ›  Alexander C.

Ajax.BeginForm在MVC中用于上传文件

  •  40
  • Alexander C.  · 技术社区  · 11 年前

    我试图用这里提到的一个例子 How to do a ASP.NET MVC Ajax form post with multipart/form-data?

    但我一直收到“失败”错误消息框

    索引.cshtml

    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <h2>Files Upload</h2>
    <script type="text/javascript">
    $(function() {
        $("#form0").submit(function(event) {
            var dataString;
            event.preventDefault();
            var action = $("#form0").attr("action");
            if ($("#form0").attr("enctype") == "multipart/form-data") {
                //this only works in some browsers.
                //purpose? to submit files over ajax. because screw iframes.
                //also, we need to call .get(0) on the jQuery element to turn it into a regular DOM element so that FormData can use it.
                dataString = new FormData($("#form0").get(0));
                contentType = false;
                processData = false;
            } else {
                // regular form, do your own thing if you need it
            }
            $.ajax({
                type: "POST",
                url: action,
                data: dataString,
                dataType: "json", //change to your own, else read my note above on enabling the JsonValueProviderFactory in MVC
                contentType: contentType,
                processData: processData,
                success: function(data) {
                    //BTW, data is one of the worst names you can make for a variable
    
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    //do your own thing
                    alert("fail");
                }
            });
        }); //end .submit()
    });
    </script>
    <div id="uploadDiv">
    @Html.Action("Files", "Home")
    </div>
    
    @using (Ajax.BeginForm("Files", "Home", new AjaxOptions { UpdateTargetId = "uploadDiv", HttpMethod = "Post" }, new { enctype = "multipart/form-data", @id="form0"}))
    {
    <div>
        <div>Upload new file:
            <input type="file" name="file" /></div>
        <input type="submit" value="Save" />
    </div>
    }
    <br />
    

    控制器

    public PartialViewResult Files(HttpPostedFileBase file)
        {
            IEnumerable<string> files;
            if ((file != null) && (file.ContentLength > 0))
            {
                string fileName = file.FileName;
                string saveLocation = @"D:\Files";
                string fullFilePath = Path.Combine(saveLocation, fileName);               
    
    
                try
                {
                    file.SaveAs(fullFilePath);
                    FileInfo fileInfo = new FileInfo(fullFilePath);
                    file.InputStream.Read(new byte[fileInfo.Length], 0, file.ContentLength);                    
                }
                catch (Exception e)
                {
                    TempData["FileUpload"] = e.Message;
                    return PartialView();
                }
                files = Directory.GetFiles(@"D:\Files\");
                return PartialView(files);
            }
            else
            {
                files = Directory.GetFiles(@"D:\Files\");
                return PartialView(files);
            }
        }
    

    文件.cshtml

    @model IEnumerable<string>
    
    @foreach (string f in Model)
    {
    <p>@f</p>
    }
    

    全球.asax

    ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
    
    3 回复  |  直到 7 年前
        1
  •  69
  •   Ashwini Verma    7 年前

    这是复杂的更好的使用 jquery forms plugin .

    以下是示例:

    Html.注册表窗体

     @using (Html.BeginForm("YourAction", "YourController"))
    {
        @Html.AntiForgeryToken()
        <input type="file" name="files"><br>
        <input type="submit" value="Upload File to Server">
    }
    

    操作方法

        [HttpPost]
        [ValidateAntiForgeryToken]
        public void YourAction(IEnumerable<HttpPostedFileBase> files)
        {
            if (files != null)
            {
                foreach (var file in files)
                {
                    // Verify that the user selected a file
                    if (file != null && file.ContentLength > 0)
                    {
                        // extract only the fielname
                        var fileName = Path.GetFileName(file.FileName);
                        // TODO: need to define destination
                        var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
                        file.SaveAs(path);
                    }
                }
            }
        }
    

    进度条

    <div class="progress progress-striped">
       <div class="progress-bar progress-bar-success">0%</div>
    </div>
    

    Jquery查询&表单脚本

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
    <script src="http://malsup.github.com/jquery.form.js"></script>
    
    <script>
    (function() {
    
    var bar = $('.progress-bar');
    var percent = $('.progress-bar');
    var status = $('#status');
    
    $('form').ajaxForm({
        beforeSend: function() {
            status.empty();
            var percentVal = '0%';
            bar.width(percentVal)
            percent.html(percentVal);
        },
        uploadProgress: function(event, position, total, percentComplete) {
            var percentVal = percentComplete + '%';
            bar.width(percentVal)
            percent.html(percentVal);
        },
        success: function() {
            var percentVal = '100%';
            bar.width(percentVal)
            percent.html(percentVal);
        },
        complete: function(xhr) {
            status.html(xhr.responseText);
        }
    }); 
    
    })();       
    </script>
    

    使现代化

    有人因为Ajax.BeginForm而两次调用操作方法,只需将其转换为Html.BeginForm.()。 有关更多说明和下载示例代码,请参阅 this blog .

        2
  •  6
  •   ViRuSTriNiTy    9 年前

    答案来自 Ashwini Verma 几乎是正确的,但有一个缺点,表格提交了两次。

    这是由于使用 Ajax.BeginForm() .使用 Html.BeginForm() 将修复它。

    下面是一个例子:

    @* do not use Ajax.BeginForm() as it would cause the form to submit twice in connection with jQuery.Form *@
    @using (var lForm = Html.BeginForm( 
      <ActionName>, <ControllerName>, FormMethod.Post, 
      new Dictionary<string, object> {{"name", <YourFormName>}, {"enctype", "multipart/form-data"}}))
    {
    
        3
  •  3
  •   Pavel Nazarov    7 年前

    您需要html5文件处理和读取客户端上的文件内容,以获得base64编码的数据。

    在客户端上,您必须放置:

    <div>
            @Html.HiddenFor(m => m.AttachmentFileName)
            @Html.HiddenFor(m => m.AttachmentFileSize)
            @Html.HiddenFor(m => m.AttachmentFileType)
            @Html.HiddenFor(m => m.AttachmentFileContentsBase64)
    
        <input type="file" name="AttachmentFile" id="AttachmentFile" onchange="handleAttachmentFileChange(this.files)" />
        @Html.ValidationMessageFor(m => m.AttachmentFile)
    </div>
    
    <script>
        function handleAttachmentFileChange(files) {
            var file = files[0];
            $("#AttachmentFileName").val(file.name);
            $("#AttachmentFileSize").val(file.size);
            $("#AttachmentFileType").val(file.type || "application/octet-stream");
    
            var fileReader = new FileReader();
            fileReader.onload = function () {
                fileReader.result;
    
                $("#AttachmentFileContentsBase64").val(fileReader.result);
            };
            fileReader.readAsDataURL(file);
        };
    </script>
    

    因此,您的代码将使用文件数据(文件名、类型、大小、base64编码的内容)填充隐藏字段。 在服务器端,您放置:

                if (AttachmentFileSize > 0)
                {
                    string fileName = AttachmentFileName.Contains("\\") ? AttachmentFileName.Substring(AttachmentFileName.LastIndexOf("\\") + 1) : AttachmentFileName;
    
                    byte[] fileBytes = Convert.FromBase64String(AttachmentFileContentsBase64.Substring(AttachmentFileContentsBase64.IndexOf(',') + 1));
    
    //save file to file system or db
    
                    ModelState.Remove("CurrentAttachmentFileId");
                    ModelState.Remove("CurrentAttachmentFileName");
    
                }
                else if (AttachmentFileSize == -1)
                {
    //remove existing file from fs or db
                }
    

    代码需要根据您的模型和逻辑进行修改,但它对我有效