How to check HttpPostedFileBase attribute file type in Asp.Net MVC 4?

I am trying to check the file type of the HttpPostedFileBase attribute to check the file type, but I cannot do this because the check passes. How can i do this?

trying to

Model

 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> 

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<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; } } 
+8
asp.net-mvc-4
source share
1 answer

Since your attribute inherits from and the existing attribute, it will need to be registered in global.asax (see this answer for an example), however do not do this in your case. Your verification code does not work, and the file type attribute should not inherit from RequiredAttribute - it needs to inherit from ValidationAttribute , and if you want to check on the client side, then you also need to implement IClientValidatable . The attribute for checking file types will be (pay attention to this code if for a property that is IEnumerable<HttpPostedFileBase> and checks each file in the collection)

 [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; } } 

It will be applied to the property as

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

and in the presentation

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

Then, client-side validation requires the following scripts (combined with jquery.validate.js and 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; } 

Please note that your code also tries to check the maximum file size, which should be a separate verification attribute. For an example of a validation attribute that validates the maximum size, see this article .

In addition, I recommend the ASP.NET MVC 3 Complete Validation Guide - Part 2 as a Good Guide to Creating Custom Validation Attributes

+10
source

All Articles