Comprobación de imagen mime, tamaño, etc. en MVC
He encontrado aquí una manera bastante buena de verificar si el archivo cargado por el usuario es una imagen o no, cómo tuve problemas cuando intenté implementarlo.
Aquí está la clase que he encontrado para verificar archivos
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;
}
return true;
}
}
Mi clase de perfil
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; }
}
Mi ProfileController después de haberlo cambiado. yo añadíHttpPostedFileBase
como argumento y también usé esta línea,if (HttpPostedFileBaseExtensions.IsImage(file) == true)
, que pensé que lo resolvería pero no hizo ninguna diferencia.
[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);
}
}
Y finalmente elSaveProfile
Método del repositorio.
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();
}
También intenté editar elSaveProfile
pero no podría implementar todas las funciones como en la clase y preferiría tener eso separado y usarlo tal como está. ¿Alguna idea de dónde me equivoqué?