【问题标题】:How to keep input type=file field value after failed validation in ASP.NET MVC?在 ASP.NET MVC 中验证失败后如何保持输入类型 = 文件字段值?
【发布时间】:2009-06-09 02:47:44
【问题描述】:

我在自己制作的 MVC 应用程序中有一个简单的表单。它包含一个文件字段,因此用户可以上传图像。这一切都很好。

问题是,如果表单提交验证失败,文件字段的内容会丢失(其他字段仍然填充,谢谢 HtmlHelpers!)。 验证失败后如何保持填充文件字段?

TIA!

【问题讨论】:

  • 我今天在这个问题上浪费了一天。已经 12 年了,我不敢相信仍然没有可用的本地解决方案。我在我的模型中使用 ASP.NET 的HttpPostFileBase 类从视图中上传图像,并且效果非常好。然后,我尝试处理这种非常简单、常见的情况,即发布的数据未能通过服务器端验证并出现繁荣。数小时摆弄隐藏输入,将流转换为字节数组和 base64 字符串等等。完全浪费时间。
  • @Philip Stratford,在这里完全相同,真的很沮丧,因为在这样一个简单的问题上浪费了几乎一整天,我最终只是将带有文件的模型返回到视图而不访问它直接,并在视图上设置一个假标签,就好像在输入中仍然选择了文件一样

标签: asp.net-mvc forms


【解决方案1】:

浏览器以这种方式设计是因为存在安全风险。无法在 HTML 源代码或 Javascript 中设置文件输入框的值。否则恶意脚本可能会在不引起用户注意的情况下窃取一些私人文件。

关于主题有an interesting information

【讨论】:

  • 是的,我了解安全原则。只是希望我描述的场景是可能的,只是因为我的用户体验受到了它的影响。 ;/
  • 解决用户必须重新选择文件的UX问题:您可以在第一次提交带有设置文件的表单时将文件存储在服务器端的临时缓存中时间。然后,如果验证失败,您只需显示文件名(或缩略图)以指示该字段已设置。验证成功后,您将从缓存中获取文件数据。
  • @tsauerwen,这违背了 MVC 无状态模型的目的。
【解决方案2】:

据我所知,您无法设置 HTML 文件输入框的值。 我建议将文件输入框与标签或文本框结合起来。

然后您可以使用文件输入框中的值填充它,以便稍后重新提交。

【讨论】:

  • 有趣...你知道有一个网站以这种方式实现它吗?寻找示例...谢谢。
  • Gmail 对其附件使用了类似的东西。文件上传后,它会变成文本。然而,这是使用 AJAX 异步完成的。
【解决方案3】:

如果文件不是太大,您可以将其 base64 并将其用作隐藏字段的值。

【讨论】:

    【解决方案4】:

    有基于 Flash 的文件上传器。尝试其中之一。如果不支持 Flash 和 java 脚本,其中一些甚至会退回到常规文件输入框。我建议寻找 jQuery 插件。

    【讨论】:

      【解决方案5】:

      我建议事先通过 ajax 进行验证并进行部分页面更新。在这种情况下,您不会丢失文件。

      【讨论】:

        【解决方案6】:

        我不同意将“不可能”标记为正确答案。 如果有人仍在寻找可能性,这里是对我有用的解决方法。我正在使用 MVC5。这个想法是使用会话变量。我是从ASP.Net Form 那里得到这个想法的。

        我的模型/视图模型(仅相关属性):

        public partial class emp_leaves
            {
                public string fileNameOrig { get; set; }
                public byte[] fileContent { get; set; }
        
                public HttpPostedFileBase uploadFile { get; set; }
            }
        

        在我的控制器(HttpPost)中: //检查

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(emp_leaves emp_leaves)
        {
            if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
            {
                emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
                emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
                emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
                Session["emp_leaves.uploadFile"] = emp_leaves.uploadFile; //saving the file in session variable here
            }
            else if (Session["emp_leaves.uploadFile"] != null)
            {//if re-submitting after a failed validation you will reach here.
                emp_leaves.uploadFile = (HttpPostedFileBase)Session["emp_leaves.uploadFile"];
                if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
                {
                    emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
                    emp_leaves.uploadFile.InputStream.Position = 0;
                    emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
                    emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);    
                }
            }
        //code to save follows here...
        }
        

        最后在我的编辑视图中:在这里,我有条件地显示文件上传控件。

        < script type = "text/javascript" >
          $("#removefile").on("click", function(e) {
            if (!confirm('Delete File?')) {
              e.preventDefault();
              return false;
            }
            $('#fileNameOrig').val('');
            //toggle visibility for concerned div
            $('#downloadlrfdiv').hide();
            $('#uploadlrfdiv').show();
            return false;
          }); <
        /script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        @model PPMSWEB.Models.emp_leaves @{ HttpPostedFileBase uploadFileSession = Session["emp_leaves.uploadFile"] == null ? null : (HttpPostedFileBase)Session["emp_leaves.uploadFile"]; } @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data"
        })) { @Html.AntiForgeryToken()
        <div class="row">
          @*irrelevant content removed*@
          <div id="downloadlrfdiv" @((!String.IsNullOrEmpty(Model.fileNameOrig) && (Model.uploadFile==n ull || uploadFileSession !=null)) ? "" : "style=display:none;")>
            <label>Attachment</label>
            <span>
                    <strong>
                        <a id="downloadlrf" href="@(uploadFileSession != null? "" : Url.Action("DownloadLRF", "emp_leaves", new { empLeaveId = Model.ID }))" class="text-primary ui-button-text-icon-primary" title="Download attached file">
                            @Model.fileNameOrig
                        </a>
                    </strong>
                    @if (isEditable && !Model.readonlyMode)
                    {
                        @Html.Raw("&nbsp");
                        <a id="removefile" class="btn text-danger lead">
                            <strong title="Delete File" class="glyphicon glyphicon-minus-sign">  </strong>
                        </a>
                    }
                    </span>
          </div>
          <div id="uploadlrfdiv" @(!(!String.IsNullOrEmpty(Model.fileNameOrig) && Model.uploadFile==n ull) && !Model.readonlyMode ? "" : "style=display:none;")>
            <label>Upload File</label> @Html.TextBoxFor(model => model.uploadFile, new { @type = "file", @class = "btn btn-default", @title = "Upload file (max 300 KB)" }) @Html.ValidationMessageFor(x => x.uploadFile)
          </div>
        </div>
        }

        【讨论】:

          【解决方案7】:

          您不能设置 HTML 文件输入框的值。作为一种解决方法,在验证后输出表单时,将文件上传框替换为隐藏的输入字段。

          提交时,您使用文件输入框中的值填充隐藏字段(稍后重新提交)。请记住在任何时候都存在文件上传或隐藏字段名称(不能同时存在):

          注意:以下代码仅用于说明/解释目的。将其替换为适合您使用的语言的代码。

          <?php /* You may need to sanitize the value of $_POST['file_upload']; 
          * this is just a start */
          if(isset($_POST['file_upload']) && !empty($_POST['file_upload'])){ ?>
          <input type="hidden" name="file_upload" value="<?php print($_POST['file_upload']); ?>" />
          <?php } else { ?>
          <input type="file" name="file_upload" />
          <?php } ?>
          

          【讨论】:

          • “请记住,文件上传或隐藏字段名称在任何时候都存在(不能同时存在)。”那么,如果在验证后,用户改变主意并想要选择不同的文件怎么办?
          猜你喜欢
          • 2011-05-11
          • 1970-01-01
          • 2011-08-24
          • 2017-10-22
          • 2012-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          相关资源
          最近更新 更多