¿Cómo validar el tipo de archivo del atributo HttpPostedFileBase en Asp.Net MVC 4?

Estoy intentando validar un tipo de archivo del atributo HttpPostedFileBase para verificar el tipo de archivo pero no puedo hacer esto porque la validación está pasando. Cómo podría hacer esto ?

molesto

Modelo

 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

 
@Html.TextBoxFor(model => Model.imagem, new { Class = "form-control", placeholder = "Informe a imagem", type = "file" }) @Html.ValidationMessageFor(model => Model.imagem)

ValidateFileAttribute

 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 formats = getValidFormats(); foreach (ImageFormat format in formats) { if(rawFormat.Equals(format)) { return true; } } return false; } private List getValidFormats() { List formats = new List(); formats.Add(ImageFormat.Png); formats.Add(ImageFormat.Jpeg); //add types here return formats; } } 

Debido a que su atributo hereda de y el atributo existente, debería estar registrado en global.asax (consulte esta respuesta para obtener un ejemplo), sin embargo , no haga eso en su caso. Su código de validación no funciona, y un atributo de tipo de archivo no debe heredar de RequiredAttribute : necesita heredar de ValidationAttribute y si desea validación del lado del cliente, entonces también necesita implementar IClientValidatable . Un atributo para validar los tipos de archivos sería (tenga en cuenta este código si se trata de una propiedad que es IEnumerable y valida cada archivo en la colección)

 [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 _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 files = value as IEnumerable; 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 GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ValidationType = "filetype", ErrorMessage = ErrorMessageString }; rule.ValidationParameters.Add("validtypes", string.Join(",", _ValidTypes)); yield return rule; } } 

Se aplicaría a una propiedad como

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

y en la vista

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

Los siguientes scripts son necesarios para la validación del lado del cliente (junto con jquery.validate.js y jquery.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; } 

Tenga en cuenta que su código también está intentando validar el tamaño máximo del archivo que debe ser un atributo de validación por separado. Para obtener un ejemplo de un atributo de validación que valida el tamaño máximo permitido, consulte este artículo .

Además, recomiendo The Complete Guide To Validation en ASP.NET MVC 3 - Parte 2 como una buena guía para crear atributos de validación personalizados