asp.net-mvc-4 - 如何在 Asp.Net MVC 4 中验证 HttpPostedFileBase 属性的文件类型?

标签 asp.net-mvc-4

我正在尝试验证 HttpPostedFileBase 的文件类型属性来检查文件类型,但我不能这样做,因为验证正在通过。我怎么能这样做?



型号

public class EmpresaModel{

[Required(ErrorMessage="Choose a file .JPG, .JPEG or .PNG file")]
[ValidateFile(ErrorMessage = "Please select a .JPG, .JPEG or .PNG file")]
public HttpPostedFileBase imagem { get; set; }

}

HTML
<div class="form-group">
      <label for="@Html.IdFor(model => model.imagem)" class="cols-sm-2 control-label">Escolha a imagem <img src="~/Imagens/required.png" height="6" width="6"></label>
       @Html.TextBoxFor(model => Model.imagem, new { Class = "form-control", placeholder = "Informe a imagem", type = "file" })
       @Html.ValidationMessageFor(model => Model.imagem)
</div>

验证文件属性
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Web;

//validate file if a valid image
public class ValidateFileAttribute : RequiredAttribute{

    public override bool IsValid(object value)
    {
        bool isValid = false;
        var file = value as HttpPostedFileBase;

        if (file == null || file.ContentLength > 1 * 1024 * 1024)
        {
            return isValid;
        }

        if (IsFileTypeValid(file))
        {
            isValid = true;
        }

        return isValid;
    }

    private bool IsFileTypeValid(HttpPostedFileBase file)
    {
        bool isValid = false;

        try
        {
            using (var img = Image.FromStream(file.InputStream))
            {
                if (IsOneOfValidFormats(img.RawFormat))
                {
                    isValid = true;
                } 
            }
        }
        catch 
        {
            //Image is invalid
        }
        return isValid;
    }

    private bool IsOneOfValidFormats(ImageFormat rawFormat)
    {
        List<ImageFormat> formats = getValidFormats();

        foreach (ImageFormat format in formats)
        {
            if(rawFormat.Equals(format))
            {
                return true;
            }
        }
        return false;
    }

    private List<ImageFormat> getValidFormats()
    {
        List<ImageFormat> formats = new List<ImageFormat>();
        formats.Add(ImageFormat.Png);
        formats.Add(ImageFormat.Jpeg);        
        //add types here
        return formats;
    }


}

最佳答案

由于您的属性继承自现有属性,因此需要在 global.asax 中注册。 (请参阅 this answer 作为示例),但是 不要在你的情况下这样做。您的验证代码不起作用,文件类型属性不应继承自 RequiredAttribute - 它需要继承自 ValidationAttribute如果你想要客户端验证,那么它还需要实现 IClientValidatable .验证文件类型的属性将是(如果属性为 IEnumerable<HttpPostedFileBase> 并验证集合中的每个文件,请注意此代码)

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FileTypeAttribute : ValidationAttribute, IClientValidatable
{
    private const string _DefaultErrorMessage = "Only the following file types are allowed: {0}";
    private IEnumerable<string> _ValidTypes { get; set; }

    public FileTypeAttribute(string validTypes)
    {
        _ValidTypes = validTypes.Split(',').Select(s => s.Trim().ToLower());
        ErrorMessage = string.Format(_DefaultErrorMessage, string.Join(" or ", _ValidTypes));
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        IEnumerable<HttpPostedFileBase> files = value as IEnumerable<HttpPostedFileBase>;
        if (files != null)
        {
            foreach(HttpPostedFileBase file in files)
            {
                if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e)))
                {
                    return new ValidationResult(ErrorMessageString);
                }
            }
        }
        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ValidationType = "filetype",
            ErrorMessage = ErrorMessageString
        };
        rule.ValidationParameters.Add("validtypes", string.Join(",", _ValidTypes));
        yield return rule;
    }
}

它将适用于属性(property)作为

[FileType("JPG,JPEG,PNG")]
public IEnumerable<HttpPostedFileBase> Attachments { get; set; }

并且在 View 中

@Html.TextBoxFor(m => m.Attachments, new { type = "file", multiple = "multiple" })
@Html.ValidationMessageFor(m => m.Attachments)

然后需要以下脚本进行客户端验证(与 jquery.validate.jsjquery.validate.unobtrusive.js 一起使用)

$.validator.unobtrusive.adapters.add('filetype', ['validtypes'], function (options) {
    options.rules['filetype'] = { validtypes: options.params.validtypes.split(',') };
    options.messages['filetype'] = options.message;
});

$.validator.addMethod("filetype", function (value, element, param) {
    for (var i = 0; i < element.files.length; i++) {
        var extension = getFileExtension(element.files[i].name);
        if ($.inArray(extension, param.validtypes) === -1) {
            return false;
        }
    }
    return true;
});

function getFileExtension(fileName) {
    if (/[.]/.exec(fileName)) {
        return /[^.]+$/.exec(fileName)[0].toLowerCase();
    }
    return null;
}

请注意,您的代码还试图验证需要作为单独验证属性的文件的最大大小。有关验证最大允许大小的验证属性示例,请参阅 this article .

另外,我推荐The Complete Guide To Validation In ASP.NET MVC 3 - Part 2作为创建自定义验证属性的好指南

关于asp.net-mvc-4 - 如何在 Asp.Net MVC 4 中验证 HttpPostedFileBase 属性的文件类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40199870/

相关文章:

entity-framework - 为什么 DbEntityEntry 的原始值与新值匹配?

asp.net-mvc-4 - 在MVC中使用参数始终重定向为空的 Action

jquery - 当其他字段更改时验证 1 个字段(不引人注目),并仅检查 1 条规则

c# - 简单发布到 Web Api

jquery - Controller 可以根据结果返回 JSON 或 HTML

c# - Angular $http 错误响应 statusText 始终未定义

javascript - 如何在加载时提交 MVC View ?

javascript - 如何通过与 jQuery 集成来检查 TempData 是否为空?

javascript - 如何将模型对象获取到 Javascript 变量

asp.net-mvc-4 - 如何将 ASP.Net MVC4 Web API 与 AngularJS 部分 View (又名 ng-include)一起使用