I have found here a pretty good way of checking whether the file uploaded by the user is a picture or not, how ever I ran into problems when I tried implementing it.
Here is the class I have found to check files
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|<as+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;
}
return true;
}
}
My profile class
public class Profile
{
public int ProfileID { get; set; }
[Required(ErrorMessage = "Please enter a profile name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a intro")]
public string Intro { get; set; }
[Required(ErrorMessage = "Please enter a description")]
public string Description { get; set; }
public decimal Rate { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
}
My ProfileController after I have changed it. I added HttpPostedFileBase
as an argument and also used this line, if (HttpPostedFileBaseExtensions.IsImage(file) == true)
, which I thought would sort it out but did not do any difference.
[HttpPost]
public ActionResult Edit(Profile profile, HttpPostedFileBase file)
{
if (HttpPostedFileBaseExtensions.IsImage(file) == true)
{
if (ModelState.IsValid)
{
repository.SaveProfile(profile);
TempData["message"] = string.Format("{0} has been saved", profile.Name);
return RedirectToAction("List");
}
else
{
// there is something wrong with the data values
return View(profile);
}
}
else
{
return View(ViewBag);
}
}
And finally the SaveProfile
method from the repository.
public void SaveProfile(Profile profile)
{
Profile dbEntry = context.Profiles.Find(profile.ProfileID);
if (profile.ProfileID == 0)
{
context.Profiles.Add(profile);
}
else
{
if (dbEntry != null)
{
dbEntry.Name = profile.Name;
dbEntry.Rate = profile.Rate;
dbEntry.Intro = profile.Intro;
dbEntry.Description = profile.Description;
if (profile.ImageData != null)
{
dbEntry.ImageData = profile.ImageData;
dbEntry.ImageMimeType = profile.ImageMimeType;
}
}
}
context.SaveChanges();
}
I also tried to edit the SaveProfile
method, but could not implement all functions as in the class and would rather just have that separate and use it as it is. Any ideas where did I go wrong?