我有一个Create动作,它接受一个实体对象和一个HttpPostedFileBase图像。该图像不属于实体模型。
我可以将实体对象保存在数据库中,将文件保存在磁盘中,但我不确定如何验证这些业务规则:
答案 0 :(得分:134)
自定义验证属性是一种方法:
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" />
}
答案 1 :(得分:8)
基于Darin Dimitrov的答案,我发现它非常有用,我有一个改编版本,允许检查多种文件类型,这是我最初寻找的。
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;
}
}
答案 2 :(得分:3)
以下是使用viewmodel进行此操作的方法,请在此处查看整个代码
Asp.Net MVC file validation for size and type 使用FileSize和FileTypes
创建如下所示的视图模型a, a:-webkit-any-link {
color: inherit;
text-decoration: none;
cursor: auto;
}
.home-tile-container-a .home-tile-half:first-child {
border-left: solid 10px #fff;
border-right: solid 5px #fff;
}
.home-tile-container-a .home-tile-half.home-tile-1 {
background-image: url(//cdn.shopify.com/s/files/1/0377/2037/t/37/assets/collection-img-1_920x.jpg?1052957349189286585);
}
.home-tile-container-a .home-tile-half {
min-height: 650px;
}
.home-tile-container-a .home-tile-half {
position: relative;
text-align: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: end;
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
background-size: cover !important;
background-position: center !important;
border-top: solid 10px #fff;
min-height: 250px;
width: 100%;
-webkit-transition: all 0.25s;
transition: all 0.25s;
}
.hover-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
background: rgba(255,255,255,0);
-webkit-transition: all 0.25s;
transition: all 0.25s;
}
.home-tile-container-a .cta-content {
padding: 15px 15px 80px;
}
.home-tile-container-a .cta-content {
padding: 15px 15px 30px;
}
.cta-content {
position: relative;
z-index: 3;
text-align: center;
}
.home-tile-container-a .cta-content h3.white {
color: #fff;
}
.home-tile-container-a .cta-content h3 {
font-family: "Helvetica";
font-size: 17px;
font-weight: bold;
letter-spacing: 0.6px;
line-height: 1.25;
color: #2c2c2c;
text-transform: uppercase;
margin-bottom: 10px;
text-decoration: none;
}
.home-tile-container-a .cta-content h3 span {
font-size: 59px;
}
.home-tile-container-a .cta-content h3 span {
display: block;
font-family: "Helvetica";
font-size: 25px;
font-weight: 500;
letter-spacing: 0.4px;
text-decoration: none;
}
.button.button--white, .livechat_button a.button--white, #storemapper-go.button--white {
background: #fff;
text-transform: uppercase;
font-family: "Gotham-Bold";
font-size: 11px;
letter-spacing: 1px;
color: #2c2c2c;
}
.button, .livechat_button a, #storemapper-go {
display: inline-block;
text-align: center;
text-transform: uppercase;
line-height: 1;
font-size: 11px;
padding: 1rem .50rem;
border-radius: 1px;
-webkit-transition: all 0.35s ease-in-out;
transition: all 0.35s ease-in-out;
font-family: "Gotham-Bold";
-webkit-transition: all 0.25s;
transition: all 0.25s;
position: relative;
}
button {
cursor: pointer;
}
button {
color: inherit;
-webkit-appearance: none !important;
background-color: transparent;
border: none;
margin: 0;
padding: 0;
}
创建自定义属性
public class ValidateFiles
{
[FileSize(10240)]
[FileTypes("doc,docx,xlsx")]
public HttpPostedFileBase File { get; set; }
}
答案 3 :(得分:1)
asp.net core 中的文件长度验证:
public async Task<IActionResult> MyAction()
{
var form = await Request.ReadFormAsync();
if (form.Files != null && form.Files.Count == 1)
{
var file = form.Files[0];
if (file.Length > 1 * 1024 * 1024)
{
ModelState.AddModelError(String.Empty, "Maximum file size is 1 Mb.");
}
}
// action code goes here
}
答案 4 :(得分:-1)
您可能还需要考虑将图像保存到数据库:
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中使用它 - 实体定义:
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提交。否则更容易访问数据流。