2016-10-23 40 views
8

Próbuję sprawdzić poprawność typu pliku atrybutu HttpPostedFileBase, aby sprawdzić typ pliku, ale nie mogę tego zrobić, ponieważ sprawdzanie poprawności mija. Jak mogłem to zrobić?Jak sprawdzić typ pliku atrybutu HttpPostedFileBase w Asp.Net MVC 4?

próbuje

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


} 
+0

Twój 'ValidateFileAttribute' nie powinny dziedziczyć' RequiredAttribute', a także nie będzie walidacji po stronie klienta. Musisz utworzyć własny atrybut sprawdzania poprawności, który dziedziczy z 'ValidationAttribute' i implementuje' IClientValidatable'. –

+0

@StephenMuecke jak mogłem to zrobić? czy masz jakiś przykład? – FernandoPaiva

+0

Ale jest trochę niejasne, co chciałbyś sprawdzić - twój plik 'file.ContentLength> 1 * 1024 * 1024' sugeruje, że chcesz mieć maksymalny rozmiar pliku (typ pliku i walidacja rozmiaru pliku to 2 oddzielne rzeczy i muszą to być 2 oddzielne atrybuty) –

Odpowiedz

10

Ponieważ atrybut dziedziczy i istniejący atrybut, to muszą być rejestrowane w global.asax (patrz this answer na przykład), jednak nie rób tego w Twoim przypadku. Twój kod sprawdzania poprawności nie działa, a atrybut typu pliku nie powinien dziedziczyć po RequiredAttribute - musi dziedziczyć po ValidationAttribute, a jeśli chcesz sprawdzać poprawność strony klienta, musi również wdrożyć IClientValidatable. Atrybut do sprawdzania typów plików będzie (uwaga ten kod jeżeli dla nieruchomości, która jest IEnumerable<HttpPostedFileBase> i sprawdza poprawność każdego pliku w kolekcji)

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

To byłaby zastosowana do nieruchomości jako

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

iw widoku

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

następujące skrypty są wtedy potrzebne do sprawdzania poprawności po stronie klienta (w połączeniu dowcipu h jquery.validate.js i 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; 
} 

pamiętać, że kod stara się również zweryfikować maksymalny rozmiar pliku, który musi być osobny atrybut walidacji. Przykład atrybutu sprawdzania poprawności, który zatwierdza maksymalny dopuszczalny rozmiar, można znaleźć pod adresem this article.

Ponadto, polecam The Complete Guide To Validation In ASP.NET MVC 3 - Part 2 jako dobry przewodnik do tworzenia niestandardowych sprawdzania poprawności atrybutów

+0

Włącza niektóre skomplikowane kodowanie JavaScript, aby włączyć (typ pliku) sprawdzanie poprawności strony klienta. Tylko mówię. – Unbreakable

+0

'' 'javascript $ .validator.addMethod (" filetype ", funkcja (wartość, element, parametr) { dla (var i = 0; i

+0

Dzięki @ TuấnTrần. –