Validate image from file in C#
JPEG's don't have a formal header definition, but they do have a small amount of metadata you can use.
- Offset 0 (Two Bytes): JPEG SOI marker (FFD8 hex)
- Offset 2 (Two Bytes): Image width in pixels
- Offset 4 (Two Bytes): Image height in pixels
- Offset 6 (Byte): Number of components (1 = grayscale, 3 = RGB)
There are a couple other things after that, but those aren't important.
You can open the file using a binary stream, and read this initial data, and make sure that OffSet 0 is 0, and OffSet 6 is either 1,2 or 3.
That would at least give you slightly more precision.
Or you can just trap the exception and move on, but I thought you wanted a challenge :)
How to validate image file format in C#
Use Image.RawFormat
. The result is an instance of the ImageFormat
class which can be compared against the static properties of ImageFormat
.
See the ImageFormat
class properties for more details.
How to check if image file is valid?
First of all, don't try to use System.Drawing
in .NET Core applications. It's deprecated and works only on Windows anyway. The MSDN docs themselves suggest using ImageSharp or SkiaSharp instead.
Image files start with bytes that identify the file format. You'll have to read at least some of the file's contents to read image metadata like the image size, resolution etc. You can use ImageSharp's Identify method to read only the format and image properties, without loading the entire image.
You can read an uploaded file's contents using IFormFile.OpenReadStream.
using var stream=image.OpenReadStream();
try
{
var imageInfo=Image.Identify(stream, out var format);
if(imageInfo!=null)
{
var formatName=format.Name;
var width=imageInfo.Width;
var height=imageInfo.Height;
}
}
catch(InvalidImageContentException exc)
{
//Invalid content ?
}
The format
parameter is an IImageFormat value that contains information about the image format, including its name and mime types.
The IImageInfo object returned contains the image dimensions, pixel type, resolution etc.
The method documentation explains that the return value will be null
if no suitable decoder is found:
The IImageInfo or null if a suitable info detector is not found.
But an exception will be thrown if the content is invalid:
InvalidImageContentException Image contains invalid content.
Without testing this, I assume that a text file will result in a null
but a file with just a GIF header without valid content will result in an exception.
You can use ImageSharp to resize the image or convert it to another format. In that case it's not enough to just load the metadata. You can use Load to load the image from the stream, detect its format and then manipulate it.
using var stream=image.OpenReadStream();
var image=Image.Load(stream, out var format);
var formatName=format.Name;
if (notOk(formatName,image.Height,image.Width))
{
using var outStream=new MemoryStream();
image.Mutate(x => x.Resize(desiredWidth, desiredHeight));
image.SaveAsPng(outStream);
outStream.Position=0;
//Store the contents of `outStream`
}
How to check Is Valid Image File in C#
I think you can check the file header.
public static ImageType CheckImageType(string path)
{
byte[] buf = new byte[2];
try
{
using (StreamReader sr = new StreamReader(path))
{
int i = sr.BaseStream.Read(buf, 0, buf.Length);
if (i != buf.Length)
{
return ImageType.None;
}
}
}
catch (Exception exc)
{
//Debug.Print(exc.ToString());
return ImageType.None;
}
return CheckImageType(buf);
}
public static ImageType CheckImageType(byte[] buf)
{
if (buf == null || buf.Length < 2)
{
return ImageType.None;
}
int key = (buf[1] << 8) + buf[0];
ImageType s;
if (_imageTag.TryGetValue(key, out s))
{
return s;
}
return ImageType.None;
}
public enum ImageType
{
None = 0,
BMP = 0x4D42,
JPG = 0xD8FF,
GIF = 0x4947,
PCX = 0x050A,
PNG = 0x5089,
PSD = 0x4238,
RAS = 0xA659,
SGI = 0xDA01,
TIFF = 0x4949
}
determine if file is an image
Check the file for a known header. (Info from link also mentioned in this answer)
The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10
Image validation in C#
FileInfo.Length
will return the current file size in bytes.
long length = new System.IO.FileInfo(path).Length;
25 Kilobytes (even though your question implicitly asks about Kilobits), is 25000 bytes. Check if less than or greater than that value.
How Do I Validate a JPEG Image in C# / .Net is not corrupted
Taking JPEG reference structure from Wikipedia, maybe you can look for EOI byte from the stream?
Determine if uploaded file is image (any format) on MVC
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.
How to check if the uploaded image file is fake using ASP.NET C#?
As @Isma commented, define "broken".
But you can try to create a new System.Drawing.Image with it. If you want to validate anything else about it, then access it's properties. For instance you can check that the image is larger than 1 pixel if that suits your purpose. If an exception is thrown creating, or during your other checks, then it is (unlikely) a valid image.
private static bool CheckImage(string filename)
{
try
{
using (var image = Image.FromFile(filename))
{
if(image.Height<2 && image.Width<2)
return false
}
return true;
}
catch (Exception ex)
{
// probably should log more information here
return false;
}
}
Related Topics
C# - How to Get Program Files (X86) on Windows 64 Bit
How to Pass the Smart Screen on Win8 When Install a Signed Application
Can One Executable Be Both a Console and Gui Application
Compute the Datetime of an Upcoming Weekday
Adding Http Headers to Httpclient
Why Should You Remove Unnecessary C# Using Directives
Notify Observablecollection When Item Changes
Calculating the Difference in Months Between Two Dates
Create a List from Two Object Lists with Linq
Workaround for Lack of 'Nameof' Operator in C# for Type-Safe Databinding
Loop Through All the Resources in a .Resx File
Mvc3 Dropdownlistfor - a Simple Example
Is Everything in .Net an Object
Casting: (Newtype) VS. Object as Newtype