web-dev-qa-db-fra.com

Déterminer si le fichier téléchargé est une image (n'importe quel format) sur MVC

Donc, j'utilise ce code pour voir:

<form action="" method="post" enctype="multipart/form-data">

  <label for="file">Filename:</label>
  <input type="file" name="file" id="file" />

  <input type="submit" />
</form>

Ceci pour le modèle:

[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {

  if (file.ContentLength > 0) {
    var fileName = Path.GetFileName(file.FileName);
    var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
    file.SaveAs(path);
  }

  return RedirectToAction("Index");
}

Fonctionne très bien sauf si l'utilisateur ajoute un fichier qui n'est pas une image. Comment puis-je assurer que le fichier téléchargé est une image? Merci

45
Erre Efe

Voici une méthode statique pour HttpPostedFileBase qui vérifie si un fichier téléchargé donné est une image:

public static class HttpPostedFileBaseExtensions
{
    public const int ImageMinimumBytes = 512;

    public static bool IsImage(this HttpPostedFileBase postedFile)
    {
        //-------------------------------------------
        //  Check the image mime types
        //-------------------------------------------
        if (!string.Equals(postedFile.ContentType, "image/jpg", StringComparison.OrdinalIgnoreCase) &&
            !string.Equals(postedFile.ContentType, "image/jpeg", StringComparison.OrdinalIgnoreCase) &&
            !string.Equals(postedFile.ContentType, "image/pjpeg", StringComparison.OrdinalIgnoreCase) &&
            !string.Equals(postedFile.ContentType, "image/gif", StringComparison.OrdinalIgnoreCase) &&
            !string.Equals(postedFile.ContentType, "image/x-png", StringComparison.OrdinalIgnoreCase) &&
            !string.Equals(postedFile.ContentType, "image/png", StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        //-------------------------------------------
        //  Check the image extension
        //-------------------------------------------
        var postedFileExtension = Path.GetExtension(postedFile.FileName);
        if (!string.Equals(postedFileExtension , ".jpg", StringComparison.OrdinalIgnoreCase)
            && !string.Equals(postedFileExtension , ".png", StringComparison.OrdinalIgnoreCase)
            && !string.Equals(postedFileExtension , ".gif", StringComparison.OrdinalIgnoreCase)
            && !string.Equals(postedFileExtension , ".jpeg", StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        //-------------------------------------------
        //  Attempt to read the file and check the first bytes
        //-------------------------------------------
        try
        {
            if (!postedFile.InputStream.CanRead)
            {
                return false;
            }
            //------------------------------------------
            //   Check whether the image size exceeding the limit or not
            //------------------------------------------ 
            if (postedFile.ContentLength < ImageMinimumBytes)
            {
                return false;
            }

            byte[] buffer = new byte[ImageMinimumBytes];
            postedFile.InputStream.Read(buffer, 0, ImageMinimumBytes);
            string content = System.Text.Encoding.UTF8.GetString(buffer);
            if (Regex.IsMatch(content, @"<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy",
                RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline))
            {
                return false;
            }
        }
        catch (Exception)
        {
            return false;
        }

        //-------------------------------------------
        //  Try to instantiate new Bitmap, if .NET will throw exception
        //  we can assume that it's not a valid image
        //-------------------------------------------

        try
        {
            using (var bitmap = new System.Drawing.Bitmap(postedFile.InputStream))
            {
            }
        }
        catch (Exception)
        {
            return false;
        }
        finally
        {
             postedFile.InputStream.Position = 0;
        }

        return true;
    }
}

Edit 2/10/2017: Selon une suggestion de modification, ajout d'une instruction finally pour réinitialiser le flux, afin de pouvoir l'utiliser ultérieurement.

86
OzB

Vous n'avez pas le compilateur sous la main, mais quelque chose comme ceci devrait faire:

try
{
   var bitmap = Bitmap.FromStream( file.InputStream );
   // valid image stream
}
catch 
{
    // not an image
}
13
Wiktor Zychla

Nous sommes en 2018 et la réponse acceptée ne fonctionne pas avec .NET CORE 2.1 car nous avons maintenant IFormFile au lieu de HttpPostedFileBase.

Voici l'adaptation de la réponse acceptée à .NET CORE 2.1 (j'ai également corrigé le bogue/typo mentionné par TomSelleck dans son commentaire à la réponse acceptée):

public static class FormFileExtensions
{
    public const int ImageMinimumBytes = 512;

    public static bool IsImage(this IFormFile postedFile)
    {
        //-------------------------------------------
        //  Check the image mime types
        //-------------------------------------------
        if (postedFile.ContentType.ToLower() != "image/jpg" &&
                    postedFile.ContentType.ToLower() != "image/jpeg" &&
                    postedFile.ContentType.ToLower() != "image/pjpeg" &&
                    postedFile.ContentType.ToLower() != "image/gif" &&
                    postedFile.ContentType.ToLower() != "image/x-png" &&
                    postedFile.ContentType.ToLower() != "image/png")
        {
            return false;
        }

        //-------------------------------------------
        //  Check the image extension
        //-------------------------------------------
        if (Path.GetExtension(postedFile.FileName).ToLower() != ".jpg"
            && Path.GetExtension(postedFile.FileName).ToLower() != ".png"
            && Path.GetExtension(postedFile.FileName).ToLower() != ".gif"
            && Path.GetExtension(postedFile.FileName).ToLower() != ".jpeg")
        {
            return false;
        }

        //-------------------------------------------
        //  Attempt to read the file and check the first bytes
        //-------------------------------------------
        try
        {
            if (!postedFile.OpenReadStream().CanRead)
            {
                return false;
            }
            //------------------------------------------
            //check whether the image size exceeding the limit or not
            //------------------------------------------ 
            if (postedFile.Length < ImageMinimumBytes)
            {
                return false;
            }

            byte[] buffer = new byte[ImageMinimumBytes];
            postedFile.OpenReadStream().Read(buffer, 0, ImageMinimumBytes);
            string content = System.Text.Encoding.UTF8.GetString(buffer);
            if (Regex.IsMatch(content, @"<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy",
                RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline))
            {
                return false;
            }
        }
        catch (Exception)
        {
            return false;
        }

        //-------------------------------------------
        //  Try to instantiate new Bitmap, if .NET will throw exception
        //  we can assume that it's not a valid image
        //-------------------------------------------

        try
        {
            using (var bitmap = new System.Drawing.Bitmap(postedFile.OpenReadStream()))
            {
            }
        }
        catch (Exception)
        {
            return false;
        }
        finally
        {
            postedFile.OpenReadStream().Position = 0;
        }

        return true;
    }
}
9
René

Pour quiconque se heurte à cela.

Vous pouvez également utiliser une file.ContentType.Contains("image") pour vérifier si le type de contenu est de type image/*. 

if(file.ContentLength > 0 && file.ContentType.Contains("image"))
{
    //valid image
}
else
{
    //not a valid image
}

Pas sûr que ce soit la meilleure pratique, mais cela fonctionne pour moi.

8
Shawn Gavett

Utilisation dans la classe d'assistance statique:

public static bool IsImage(HttpPostedFileBase postedFile)
    {
        try  {
              using (var bitmap = new System.Drawing.Bitmap(postedFile.InputStream))
                    {                        
                            return !bitmap.Size.IsEmpty;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
    }

Utilisation dans le modèle de vue ASP.NET MVC:

public class UploadFileViewModel
    {
        public HttpPostedFileBase postedFile { get; set; }

        public  bool IsImage()
        {
            try  {
                  using (var bitmap = new System.Drawing.Bitmap(this.postedFile.InputStream))
                        {                        
                                return !bitmap.Size.IsEmpty;
                        }
                    }
                    catch (Exception)
                    {
                        return false;
                    }
                }
        }
    }

Cet exemple vérifie si l'image est une image réelle et vous pouvez le modifier et le convertir.

Il utilise la mémoire comme exemple de V8 de six litres, il devrait donc être utilisé lorsque vous voulez vraiment savoir en quoi consiste cette image.

8
TheZodchiy

Mise en œuvre de manière beaucoup plus propre,

public static class FileExtensions
{
    private static readonly IDictionary<string, string> ImageMimeDictionary = new Dictionary<string, string>
    {
        { ".bmp", "image/bmp" },
        { ".dib", "image/bmp" },
        { ".gif", "image/gif" },
        { ".svg", "image/svg+xml" },
        { ".jpe", "image/jpeg" },
        { ".jpeg", "image/jpeg" },
        { ".jpg", "image/jpeg" },
        { ".png", "image/png" },
        { ".pnz", "image/png" }
    };

    public static bool IsImage(this string file)
    {
        if (string.IsNullOrEmpty(file))
        {
            throw new ArgumentNullException(nameof(file));
        }

        var extension = Path.GetExtension(file);
        return ImageMimeDictionary.ContainsKey(extension.ToLower());
    }
}
1
Arun Selva Kumar

Dans un premier temps, vous devez former une liste blanche autour des types MIME acceptables par rapport à la propriété ContentType

0
Daniel A. White
public static ImageFormat GetRawImageFormat(byte[] fileBytes)
{
    using (var ms = new MemoryStream(fileBytes))
    {
        var fileImage = Image.FromStream(ms);
        return fileImage.RawFormat;
    }
}

Usage:

if (GetRawImageFormat(fileBytes).IsIn(ImageFormat.Jpeg, ImageFormat.Png, ImageFormat.Gif))
    {
        //do somthing
    }
0
CS-Beginner