Determine if uploaded file is image (any format) on MVC

你离开我真会死。 提交于 2019-12-17 03:52:00

问题


So I'm using this code for view:

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

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

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

This for model:

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

Works great unless the user add a file which isn't an image. How can I assure the file uploaded is an image. Thanks


回答1:


In case it can helps anyone, Here is a static method for HttpPostedFileBase that checks if a given uploaded file is an 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: According to a suggested edit, added a finally statement to reset the stream, so we can use it later.




回答2:


It's 2018 and the accepted answer does not work with .NET CORE 2.1 because we now have IFormFile instead of HttpPostedFileBase.

Here comes the adaption of the accepted answer to .NET CORE 2.1 (I also fixed the bug/typo mentioned by TomSelleck in his comment to the accepted answer):

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



回答3:


Don't have the compiler at hand but something like this should do:

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



回答4:


For anyone that runs into this.

You could also use a file.ContentType.Contains("image") to check if the content type is of image/*.

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

Not sure if this is best practice, but it works for me.




回答5:


Use in static helper class:

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

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

This example checks to see whether the image is a real image, and you can modify and convert it.

It eats memory as an example of six-liter V8, so it should be used when you really want to know what this image.




回答6:


Implementation in much more cleaner way,

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



回答7:


As a first step, you should form a white list around the acceptable MIME types against the ContentType property.




回答8:


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
    }



回答9:


For IFormFile : It is based on a logic that if .NET can treat the file as a valid image and can be processed further, then it is a valid image.

using System.Drawing;

    private bool IsValidImageFile(IFormFile file) {

      try {
        var isValidImage = Image.FromStream(file.OpenReadStream());
      } catch {
        return false;
      }

      return true;
    }



回答10:


in the server side compare with content type if its matching with your required uploaded format then proceed or else return error message



来源:https://stackoverflow.com/questions/11063900/determine-if-uploaded-file-is-image-any-format-on-mvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!