客户端文件大小结束格式验证。为什么JS会阻止文件上传?

时间:2013-03-19 02:21:34

标签: javascript jquery asp.net asp.net-mvc asp.net-mvc-4

<script type="text/javascript">
    $.validator.addMethod('accept', function () { return true; });
</script>
@using (Html.BeginForm("Create","My controller",FormMethod.Post,new {enctype = "multipart/form-data"})) {
    @Html.ValidationSummary(true)
    <fieldset>
        <div class="editor-field">
            <input type="file" id="File" name="File" accept="image/*" />
        </div>

我无法上传打开JS的文件(当我点击提交时,文件输入周围会出现一个黄色框,没有其他事情发生)。

当我关闭JS时,我的表单提交。

顶部有3行,文件上传表格可以与JS一起使用。我在我的一个项目中发现了这些,但我不记得他们做了什么或为什么需要它们。

你能解释一下吗?

修改

视图的整个代码。

@using EDoctor.Properties
@using EDoctor.Resources
@model EDoctor.Models.DoctorProfileViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
    $.validator.addMethod('accept', function () { return true; });
</script>
@using (Html.BeginForm("Create","DoctorProfiles",FormMethod.Post,new {enctype = "multipart/form-data"})) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>DoctorProfiles</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Model.PhotoFileUrl)
        </div>
        <div class="editor-field">
            <input type="file" id="File" name="File" accept="image/*" />
            @Html.ValidationMessage("UploadFile")
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Model.LicenseNumber)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Model.LicenseNumber)
            @Html.ValidationMessageFor(model => model.Model.LicenseNumber)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Model.FirstName)
            @Html.ValidationMessageFor(model => model.Model.FirstName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Model.LastName)
            @Html.ValidationMessageFor(model => model.Model.LastName)
        </div>

        @Html.HiddenFor(model => model.Model.UserId)

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

3 个答案:

答案 0 :(得分:3)

您已关闭文件类型的验证。默认情况下,html文件类型具有属性 accept 某些类型的文件。 Accept字段控制允许的文件类型。

$.validator.addMethod('accept', function () { return true; });

添加一个始终返回true(success)的验证方法。结果是任何文件类型

答案 1 :(得分:2)

我认为你有一个标记为必需的模型属性,但它不在任何地方的表单上。我明白这一点:

@Html.LabelFor(model => model.Model.PhotoFileUrl)

和这个

@Html.ValidationMessage("UploadFile")
在您的表单中

,但这是您用于文件元素的标记:

<input type="file" id="File" name="File" accept="image/*" />

因此,您的模型似乎可能在[Required]字段上具有UploadFile属性。这可能会触发不显眼的验证,因为验证器无法找到要验证的字段。

答案 2 :(得分:1)

在Dave和Tieson的帮助下,我终于解决了它并得到了一个很好的客户端验证。我的情况有人还需要执行客户端文件验证我将在这里发布详细说明:

一般想法

  • MVC / jQuery不理解 accept =“image / *”的方式。它不接受* .png例如
  • 除非您添加 @ Html.ValidationMessage(“file_input”),否则将无法显示错误消息。因此,当你试图提交你的表格时,你得到的只是场地周围的黄色框架(铬)或什么都没有,脸上有一个大的WTF。
  • @ Html.ValidationMessage 生成以下html:

    <span class="field-validation-valid" data-valmsg-for="file_input" data-valmsg-replace="true"></span>
    
  • 如果jQuery验证器在html中找到上面的行,它将坚持放置它自己的验证消息。

如果我们想在客户端验证图像格式和大小并获得自定义/本地化验证消息,该怎么办?我们可能会使用某种插件,但你也可以这样做:

<div class="editor-field">
    <input type="file" id="file_input" name="file_input" onchange='validate_image_upload(this)' accept="image/*" class="fileToUpload" data-error-msg-max-size="@string.Format(ErrorMessages.FileSizeExceedsMaxSize,Settings.Default.OfficialMaxFileUploadSizeMBs)" data-error-msg-file-format="@string.Format(ErrorMessages.IncorrectImageFile, Settings.Default.AcceptableImageFormats)" data-max-size="1500000" data-acceptable-formats="@Settings.Default.AcceptableImageFormats"/>
    @Html.ValidationMessage("file_input[custom]")
</div>

请注意在ValidationMessage中将'[custom]'添加到'file_input'

我们这样做是为了欺骗jQuery并防止它放置自己的验证消息。 (如果你不改变它,jQuery将没有任何怜悯和屠杀你自己的消息)。我们仍然可以获得漂亮的原始MVC样式错误消息,并可以使用Razor生成它。我们只需要以某种方式设置它的内容。这可以通过在View文件(在其他脚本标记下)添加以下代码来完成:

<script type="text/javascript">
    $.validator.addMethod('accept', IsFileValid);
</script>

现在发生了什么?

  • 我们忽略了jQuery通过注入我们自己的方法接受图像文件的奇怪想法(IsFileValid)
  • 如果IsFileValid返回false,jQuery仍然想要自己的验证消息。但它没有地方可以把它(我们在ValidationMessage中添加'[custom]')现在它生成以下html:

    <span class="field-validation-valid" data-valmsg-for="file_input[custom]" data-valmsg-replace="true"></span>
    

和jQuery正在寻找

<span class="field-validation-valid" data-valmsg-for="file_input" data-valmsg-replace="true"></span>
  • 它什么都没找到,所以它只是突出显示输入字段并阻止提交按钮。 (很好,有一半的工作是为我们完成的)

  • 我们现在所做的只是放置我们自己的验证消息,可以通过此脚本完成。 (IsFileValid将处理所有事情,因此您不必再做上述任何事情。)

    function IsFileValid(value, field) {
        return validate_image_upload(field);
    }
    
    String.prototype.format = function () {
        var s = arguments[0];
        for (var i = 0; i < arguments.length - 1; i++) {
            var reg = new RegExp("\\{" + i + "\\}", "gm");
            s = s.replace(reg, arguments[i + 1]);
        }
    
        return s;
    };
    
    function validate_image_upload(field) {
        var isValid = validate_image_size(field) &&
            validate_image_format(field);
    
        if (isValid)
            remove_error_message(field);
        else
            append_error_message(field);
    
        return isValid;
    }
    
    function validate_image_format(field) {
        var ext = $(field).val().split('.').pop().toLowerCase();
        var acceptabelExtensions = $(field).data("acceptableFormats").toLowerCase().split(',');
        if ($.inArray(ext, acceptabelExtensions) == -1) {
            var msg = String.prototype.format($(field).data("errorMsgFileFormat"), acceptabelExtensions.join(', '));
            append_error_message(field, msg);
            return false;
        } else {
            return true;
        }
    }
    
    function validate_image_size(field) {
        if (field.files[0].size > $(field).data("maxSize")) {
            append_error_message(field, $(field).data("errorMsgMaxSize"));
            return false;
        } else {
            return true;
        }
    }
    
    function append_error_message(field, msg) {
        var f = $(field);
        var sib = f.siblings();
        $.each(sib, function (i, v) {
            var name1 = $(v).data("valmsgFor");
            var name2 = f.attr("name") + "[custom]";
            if (name1 == name2) {
                $(v).attr("class", "field-validation-error");
                $(v).text(msg);
                return;
            }
        });
    }
    
    function remove_error_message(field) {
        var f = $(field);
        var sib = f.siblings();
        $.each(sib, function (i, v) {
            var name1 = $(v).data("valmsgFor");
            var name2 = f.attr("name") + "[custom]";
            if (name1 == name2) {
                $(v).attr("class", "field-validation-valid");
                return;
            }
        });
    }
    

<强>说明

  • 脚本验证文件扩展名和文件大小
  • 显示/隐藏验证消息(找到 file_input [custom] 并将其映射到 file_input
  • IsFileValid方法也被挂钩到文件输入的更改(因此如果您选择了错误的图像,它会立即显示na错误)
  • 最大文件大小和接受的文件扩展名通过设置中的视图传递。 (参见输入标签)。
  • 验证消息通过视图表单资源传递 - 因此可以轻松进行本地化(请参阅输入标记)
  • 当然不安全。它只是用户友好。请记住也要执行服务器端验证。
希望我能救几个小时的人。 :)