Как проверить загруженный файл в ASP.NET MVC?
У меня есть действие Create, которое принимает объект сущности и образ HttpPostedFileBase. Изображение не принадлежит модели сущности.
Я могу сохранить объект в базе данных и файлов на диске, но я не уверен, как проверить эти бизнес-правила:
- изображения требуется
- тип контента должен быть "image / png"
- не должно превышать 1 МБ
4 ответа:
пользовательский атрибут проверки-это один из способов:
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; } }
и затем применить на вашей модели:
public class MyViewModel { [ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")] public HttpPostedFileBase File { get; set; } }
контроллер может выглядеть так:
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"); } }
вид:
@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" /> }
основываясь на ответе Дарина Димитрова, который я нашел очень полезным, у меня есть адаптированная версия, которая позволяет проверять несколько типов файлов, что я изначально искал.
public override bool IsValid(object value) { bool isValid = false; var file = value as HttpPostedFileBase; if (file == null || file.ContentLength > 1 * 1024 * 1024) { return isValid; } if (IsFileTypeValid(file)) { isValid = true; } return isValid; } private bool IsFileTypeValid(HttpPostedFileBase file) { bool isValid = false; try { using (var img = Image.FromStream(file.InputStream)) { if (IsOneOfValidFormats(img.RawFormat)) { isValid = true; } } } catch { //Image is invalid } return isValid; } private bool IsOneOfValidFormats(ImageFormat rawFormat) { List<ImageFormat> formats = getValidFormats(); foreach (ImageFormat format in formats) { if(rawFormat.Equals(format)) { return true; } } return false; } private List<ImageFormat> getValidFormats() { List<ImageFormat> formats = new List<ImageFormat>(); formats.Add(ImageFormat.Png); formats.Add(ImageFormat.Jpeg); formats.Add(ImageFormat.Gif); //add types here return formats; } }
вот способ сделать это с помощью viewmodel, взгляните на весь код здесь
Asp.Net проверка файла MVC на размер и тип Создайте viewmodel, как показано ниже, с помощью FileSize и FileTypes
public class ValidateFiles { [FileSize(10240)] [FileTypes("doc,docx,xlsx")] public HttpPostedFileBase File { get; set; } }
создать пользовательские атрибуты
public class FileSizeAttribute : ValidationAttribute { private readonly int _maxSize; public FileSizeAttribute(int maxSize) { _maxSize = maxSize; } //..... //..... } public class FileTypesAttribute : ValidationAttribute { private readonly List<string> _types; public FileTypesAttribute(string types) { _types = types.Split(',').ToList(); } //.... //... }
вы можете рассмотреть возможность сохранения изображения в базу данных также:
using (MemoryStream mstream = new MemoryStream()) { if (context.Request.Browser.Browser == "IE") context.Request.Files[0].InputStream.CopyTo(mstream); else context.Request.InputStream.CopyTo(mstream); if (ValidateIcon(mstream)) { Icon icon = new Icon() { ImageData = mstream.ToArray(), MimeType = context.Request.ContentType }; this.iconRepository.SaveOrUpdate(icon); } }
Я использую это с определением NHibernate-entity:
public Icon(int id, byte[] imageData, string mimeType) { this.Id = id; this.ImageData = imageData; this.MimeType = mimeType; } public virtual byte[] ImageData { get; set; } public virtual string MimeType { get; set; }
затем вы можете вернуть изображение в виде FileContentResult:
public FileContentResult GetIcon(int? iconId) { try { if (!iconId.HasValue) return null; Icon icon = this.iconRepository.Get(iconId.Value); return File(icon.ImageData, icon.MimeType); } catch (Exception ex) { Log.ErrorFormat("ImageController: GetIcon Critical Error: {0}", ex); return null; } }
обратите внимание, что это с помощью ajax submit. Легче получить доступ к потоку данных в противном случае.