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

3 回答 3

3

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

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

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

于 2013-03-19T02:42:08.047 回答
2

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

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

还有这个

@Html.ValidationMessage("UploadFile")

在您的表单中,但这是您用于文件元素的标记:

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

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

于 2013-03-19T17:39:36.587 回答
1

在 Dave 和 Tieson 的帮助下,我终于解决了这个问题,并获得了很好的客户端验证。如果有人还需要执行客户端文件验证,我将在此处发布详细说明:

总体思路

  • MVC/jQuery 不理解accept="image/*"您期望的方式。它不接受 *.png 例如
  • 除非您添加@Html.ValidationMessage("file_input")否则将无处显示错误消息。结果,当您尝试提交表单时,您得到的只是字段周围的黄色框(chrome)或什么都没有,并且您的脸上出现了一个大的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 来生成它。我们只需要以某种方式设置它的内容。这可以通过在您的视图文件顶部(在其他脚本标签下)添加以下代码来完成:

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

现在会发生什么?

  • 我们通过注入我们自己的方法(IsFileValid)来忽略jQuery接受图像文件的奇怪想法
  • 如果 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 方法也与文件输入的 onchange 挂钩(因此,如果您选择错误的图像,它会立即显示错误)
  • 最大文件大小和接受的文件扩展名通过设置中的视图传递。(见输入标签)。
  • 验证消息通过视图表单资源传递 - 因此可以轻松本地化(请参阅输入标签)
  • 当然,这并不安全。这只是用户友好的。记住也要执行服务器端验证。

希望我救了人几个小时。:)

于 2013-03-20T00:04:39.290 回答