Un attribut de validation personnalisé est une solution :
public class ValidateFileAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var file = value as HttpPostedFileBase;
if (file == null)
{
return false;
}
if (file.ContentLength > 1 * 1024 * 1024)
{
return false;
}
try
{
using (var img = Image.FromStream(file.InputStream))
{
return img.RawFormat.Equals(ImageFormat.Png);
}
}
catch { }
return false;
}
}
et ensuite appliquer sur votre modèle :
public class MyViewModel
{
[ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")]
public HttpPostedFileBase File { get; set; }
}
Le contrôleur pourrait ressembler à ceci :
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// The uploaded image corresponds to our business rules => process it
var fileName = Path.GetFileName(model.File.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
model.File.SaveAs(path);
return Content("Thanks for uploading", "text/plain");
}
}
et la vue :
@model MyViewModel
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.LabelFor(x => x.File)
<input type="file" name="@Html.NameFor(x => x.File)" id="@Html.IdFor(x => x.File)" />
@Html.ValidationMessageFor(x => x.File)
<input type="submit" value="upload" />
}