web-dev-qa-db-fra.com

Comment valider le fichier téléchargé dans ASP.NET MVC?

J'ai une action Créer qui prend un objet entité et une image HttpPostedFileBase. L'image n'appartient pas au modèle d'entité.

Je peux enregistrer l'objet entité dans la base de données et le fichier sur disque, mais je ne sais pas comment valider ces règles métier:

  • L'image est requise
  • Le type de contenu doit être "image/png"
  • Ne doit pas dépasser 1 Mo
64
user386167

Un attribut de validation personnalisé est une façon de procéder:

public class ValidateFileAttribute : RequiredAttribute
{
    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file == null)
        {
            return false;
        }

        if (file.ContentLength > 1 * 1024 * 1024)
        {
            return false;
        }

        try
        {
            using (var img = Image.FromStream(file.InputStream))
            {
                return img.RawFormat.Equals(ImageFormat.Png);
            }
        }
        catch { }
        return false;
    }
}

puis appliquez sur votre modèle:

public class MyViewModel
{
    [ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")]
    public HttpPostedFileBase File { get; set; }
}

Le contrôleur pourrait ressembler à ceci:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // The uploaded image corresponds to our business rules => process it

        var fileName = Path.GetFileName(model.File.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
        model.File.SaveAs(path);

        return Content("Thanks for uploading", "text/plain");
    }
}

et la vue:

@model MyViewModel

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.LabelFor(x => x.File)
    <input type="file" name="@Html.NameFor(x => x.File)" id="@Html.IdFor(x => x.File)" />
    @Html.ValidationMessageFor(x => x.File)
    <input type="submit" value="upload" />
}
135
Darin Dimitrov

Sur la base de la réponse de Darin Dimitrov que j'ai trouvée très utile, j'ai une version adaptée qui permet de vérifier plusieurs types de fichiers, ce que je cherchais initialement.

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);
        formats.Add(ImageFormat.Gif);
        //add types here
        return formats;
    }
}
8
Elizabeth Hamlet

Voici une façon de le faire en utilisant viewmodel, jetez un oeil à tout le code ici

Validation du fichier MVC Asp.Net pour la taille et le type Créez un modèle de vue comme indiqué ci-dessous avec FileSize et FileTypes

public class ValidateFiles
{
    [FileSize(10240)]
    [FileTypes("doc,docx,xlsx")]
    public HttpPostedFileBase File { get; set; }
}

Créer des attributs personnalisés

public class FileSizeAttribute : ValidationAttribute
{
    private readonly int _maxSize;

    public FileSizeAttribute(int maxSize)
    {
        _maxSize = maxSize;
    }
    //.....
    //.....
}



public class FileTypesAttribute : ValidationAttribute
{
    private readonly List<string> _types;

    public FileTypesAttribute(string types)
    {
        _types = types.Split(',').ToList();
    } 
    //....
    //...
}
3
Jeff D

Et validation de la longueur du fichier dans noyau asp.net :

public async Task<IActionResult> MyAction()
{
    var form = await Request.ReadFormAsync();
    if (form.Files != null && form.Files.Count == 1)
    {
        var file = form.Files[0];
        if (file.Length > 1 * 1024 * 1024)
        {
            ModelState.AddModelError(String.Empty, "Maximum file size is 1 Mb.");
        }
    }
    // action code goes here
}
1
Evgeny Levin