我正在尝试验证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>
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;
}
}
答案 0 :(得分:15)
由于您的属性继承自现有属性,因此需要在global.asax
中注册(例如,请参阅this answer),但不在您的案件。您的验证代码不起作用,文件类型属性不应继承自RequiredAttribute
- 它需要从ValidationAttribute
继承,如果您想要客户端验证,那么它还需要实现{{1} }}。验证文件类型的属性是(如果属性为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
请注意,您的代码还尝试验证文件的最大大小,该大小需要是单独的验证属性。有关验证最大允许大小的验证属性的示例,请参阅this article。
此外,我建议The Complete Guide To Validation In ASP.NET MVC 3 - Part 2作为创建自定义验证属性的良好指南
答案 1 :(得分:0)
请注意,EndsWith默认情况下区分大小写。所以我要改变这个:
if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e)))
对此
if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e, StringComparison.InvariantCultureIgnoreCase)))