2012-06-16 11 views
40

więc używam tego kodu do widoku:Ustal, czy przesłany plik jest obraz (dowolny format) na MVC

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

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

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

To dla modelu

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

Działa świetnie, chyba że użytkownik dodać plik, który nie jest obrazem. Jak mogę zapewnić, że przesłany plik jest obrazem. Dzięki

+0

istnieje wiele formatów graficznych. –

+0

@ DanielA.White Dokładnie o to pytam. Ustal, że jest to dowolny format obrazu, ale obraz. –

+1

Możesz sprawdzić 'ContentType'' file' jako podstawową formę sprawdzania poprawności. Jeśli to nie wystarczy, możesz spróbować zerknąć na "nagłówek" strumienia plików i sprawdzić, czy pasuje do dowolnego z typów obrazów, które wspierasz, ala http://stackoverflow.com/questions/210650/validate -image-from-file-in-c-sharp – HackedByChinese

Odpowiedz

73

W przypadku może on pomaga każdemu, tutaj jest statyczna metoda HttpPostedFileBase, który sprawdza, czy dany plik jest przesłany obraz:

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

    public static bool IsImage(this HttpPostedFileBase 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.InputStream.CanRead) 
      { 
       return false; 
      } 

      if (postedFile.ContentLength < ImageMinimumBytes) 
      { 
       return false; 
      } 

      byte[] buffer = new byte[512]; 
      postedFile.InputStream.Read(buffer, 0, 512); 
      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; 
    } 
} 

Edycja 10.02.2017: Według sugerowanej edycji, dodany Ostateczne polecenie resetowania strumienia, abyśmy mogli go później użyć.

+0

Jaki masz pomysł na te typy plików: ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pps", ".ppsx" ', proszę. –

+0

Oprócz sprawdzania poprawności rozszerzenia pliku, możesz również sprawdzić poprawność pierwszych bajtów (patrz na przykład http: // serverfault.com/questions/338087/making-libmagic-file-detect-docx-files/377792 # 377792). W związku z tym pamiętaj, że są to skompresowane pliki ZIP (więc pamiętaj o typie mime), które dają ci XML, możesz spróbować sprawdzić poprawność tego formatu XML, choć myślę, że będzie to trudne, inaczej niż w przypadku sprawdzania poprawności obrazu powyżej. Pomysł, który może działać, to użycie Office COM i próba załadowania dokumentów, aby sprawdzić, czy nie ma błędów. Takie podejście nie zadziała jednak we wszystkich środowiskach. – OzB

+1

Świetna odpowiedź, dzięki! –

12

Nie masz kompilatora pod ręką, ale coś takiego powinien zrobić:

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

W pierwszym kroku należy utworzyć białą listę wokół dopuszczalnych typów MIME przeciwko własności ContentType.

+2

To nie zadziała w przypadku spreparowanych żądań, gdy typ MIME nie odpowiada treści strumienia. –

7

Zastosowanie w statycznej klasy pomocnika:

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

Zastosowanie w ASP.NET MVC viewmodel:

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

Ten przykład sprawdza, czy obraz jest prawdziwy obraz, można modyfikować i przekonwertuj to.

Zjada pamięć jako przykład sześciocylindrowego V8, więc powinno się go używać, gdy naprawdę chcemy się dowiedzieć, jaki to obraz.

+1

proszę również podać trochę wyjaśnienia. : D –

+0

ok, dziękuję za przypomnienie mi o tym – TheZodchiy

+1

Myślę, że jest to jedyne rozwiązanie, któremu można zaufać – MonsterMMORPG

-2

na stronie serwera porównać typu zawartości, jeśli jego dopasowanie z wymaganym formacie przesłanym następnie postępować albo zwrócić komunikat o błędzie

+0

Nie ograniczy to użytkowników do wybierania innych typów MIME. – refactor

7

Dla każdego, który biegnie do tego.

Można również użyć parametru file.ContentType.Contains("image"), aby sprawdzić, czy typem treści jest obraz/*.

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

Nie jestem pewien, czy to najlepsza praktyka, ale działa dla mnie.

0

Wdrożenie w znacznie bardziej czystszego sposób

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()); 
    } 
} 
Powiązane problemy