Asp.net-Mvc-4
如何在 Asp.Net MVC 4 中驗證 HttpPostedFileBase 屬性的文件類型?
我正在嘗試驗證文件類型的
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(請參閱此答案以獲取範例),但是在您的情況下不要這樣做。您的驗證程式碼不起作用,並且文件類型屬性不應繼承自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; } }它將應用於屬性
[FileType("JPG,JPEG,PNG")] public IEnumerable<HttpPostedFileBase> Attachments { get; set; }並且在視圖中
@Html.TextBoxFor(m => m.Attachments, new { type = "file", multiple = "multiple" }) @Html.ValidationMessageFor(m => m.Attachments)然後,客戶端驗證需要以下腳本(與
jquery.validate.js和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; }請注意,您的程式碼還試圖驗證文件的最大大小,這需要是一個單獨的驗證屬性。有關驗證最大允許大小的驗證屬性範例,請參閱本文。
此外,我推薦ASP.NET MVC 3 中的驗證完整指南 - 第 2 部分作為創建自定義驗證屬性的良好指南
請注意 EndsWith 預設情況下區分大小寫。所以我會改變這個:
if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e)))對此
if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e, StringComparison.OrdinalIgnoreCase)))