【发布时间】:2014-12-23 16:32:00
【问题描述】:
我有一个名为:ValidateFileAttribute 的文件,用于验证图像上传的正确输入。像这样:
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.Jpeg);
}
}
catch { }
return false;
}
}
这是模型的属性:
[DisplayName("Image")]
[ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")]
public byte[] Image { get; set; }
这是我的观点:
<div id="upload-choices">
<div class="editor-label">
@Html.LabelFor(m => m.Image)
@Html.ValidationMessageFor(model => model.Image)
</div>
<div class="editor-row">
@Html.ValidationSummary(true)
</div>
</div>
但是每次我尝试上传图片时(它是 png 并且小于 1 mb)我都会收到这个错误:
var file = value as HttpPostedFileBase; 文件为空。
谢谢
这是完整的视图:
<div id="tabs-2">
@using (Html.BeginForm("EditPhotos", "Account", FormMethod.Post, new { id = "form", enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Photos</h4>
<hr />
@Html.HiddenFor(model => model.Id)
<div class="editor-label">
@Html.LabelFor(model => model.DisplayItem)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DisplayItem)
</div>
<div id="upload-choices">
<div class="editor-label">
@Html.LabelFor(m => m.Image)
@Html.ValidationMessageFor(model => model.Image)
</div>
<div class="editor-row">
@Html.ValidationSummary(true)
</div>
</div>
<br />
<div class="table-responsive">
<table class="table">
<tr>
<th><img width="200" height="150" src="@Url.Action("GetImage", "Account", new { id = Model.Id })"></th>
</tr>
</table>
</div>
<input type="file" name="file" class="filestyle" data-buttontext="Find file">
<br />
<div class="progress progress-striped">
<div class="progress-bar progress-bar-success">0%</div>
</div>
<div id="status"></div>
<br />
@*@Html.ActionLink("Upload photos", "Upload")*@
<div class="pull-left">
<div class="col-md-offset-0">
<input type="submit" value="Save" accept="image/x-png, image/gif, image/jpeg" class="btn btn-default pull-left" />
</div>
</div>
</div>
}
<br /><br />
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</div>
这是动作方法:
[HttpPost]
public ActionResult EditPhotos(UserProfile userprofile, HttpPostedFileBase file)
{
if (file != null)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
ModelState.Clear();
}
if (ModelState.IsValid)
{
string username = User.Identity.Name;
// Get the userprofile
UserProfile user = db.userProfiles.FirstOrDefault(u => u.UserName.Equals(username));
// Update fields
user.Image = new byte[file.ContentLength];
file.InputStream.Read(user.Image, 0, file.ContentLength);
user.ImageMimeType = file.ContentType;
db.Entry(user).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
return RedirectToAction("Edit", routeValues: new { controller = "Account", activetab = "tabs-2" });
}
并且没有:[ValidateFile(ErrorMessage = "请选择小于 1MB 的 PNG 图像")] 我可以上传图像。但当然必须有验证
我现在是这样的:
public override bool IsValid(object value)
{
var ImageProfile = value as byte[];
if (ImageProfile == null)
{
return false;
}
if (ImageProfile.ContentLength > 1 * 1024 * 1024)
{
return false;
}
try
{
using (var img = Image.FromStream(ImageProfile.InputStream))
{
return img.RawFormat.Equals(ImageFormat.Jpeg);
}
}
catch { }
return false;
}
和属性:
[DisplayName("ImageProfile")]
[ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")]
public byte[] ImageProfile { get; set; }
好吧,我现在是这样的:
public override bool IsValid(object value)
{
var ImageProfile = value as byte[];
if (ImageProfile == null)
{
return false;
}
if (ImageProfile.Length > 1 * 1024 * 1024)
{
return false;
}
try
{
using (var binaryReader = new BinaryReader(HttpContext.Current.Request.Files[0].InputStream))
{
//return img.RawFormat.Equals(ImageFormat.Jpeg);
ImageProfile = binaryReader.ReadBytes(HttpContext.Current.Request.Files[0].ContentLength);
}
}
catch { }
return false;
}
但 ImageProfile 仍然为空??怎么可能?
如果我改变这个:
[DisplayName("ImageProfile")]
[ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")]
public HttpPostedFileBase ImageProfile { get; set; }
那么这将不再起作用:
user.ImageProfile = new byte[file.ContentLength];
file.InputStream.Read(user.ImageProfile, 0, file.ContentLength);
在这个方法中:
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult EditPhotos(UserProfile userprofile, HttpPostedFileBase file)
{
if (file != null)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath(@"\\Images"), fileName);
file.SaveAs(path);
ModelState.Clear();
}
if (ModelState.IsValid)
{
string username = User.Identity.Name;
// Get the userprofile
UserProfile user = db.userProfiles.FirstOrDefault(u => u.UserName.Equals(username));
// Update fields
user.ImageProfile = new byte[file.ContentLength];
file.InputStream.Read(user.ImageProfile, 0, file.ContentLength);
user.ImageMimeType = file.ContentType;
db.Entry(user).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
return RedirectToAction("Edit", routeValues: new { controller = "Account", activetab = "tabs-2" });
}
还有这个:
public ActionResult GetImage(int id) { var image = db.userProfiles.Where(p => p.Id == id).Select(img => img.ImageProfile).FirstOrDefault();
var stream = new MemoryStream(image.ToArray());
return new FileStreamResult(stream, "image/jpeg");
}
但在这一行仍然报错:var stream = new MemoryStream(image.ToArray());
【问题讨论】:
-
也许您实际上并未上传文件。我没有看到表单元素,因此我不能说你是否做对了。表单的内容类型应为
multipart/form-data。你调试过你的代码吗?你属性中的value真的是null吗? -
感谢您的评论,我更新了我的帖子
-
您模型上的属性是
byte[],但您的验证器试图将值转换为HttpPostedFileBase,您不能这样做,值的类型需要与类型兼容在您的模型上,即更改您的验证器以使用字节数组.. -
您的
input[type=file]被命名为file,它会自动绑定到控制器中的file对象。没有与您的Image属性相关的输入。 -
是的,但如果我尝试这个:var file = value as byte[];我不能做这个文件。ContentLength
标签: c# asp.net-mvc-4 visual-studio-2013 entity-framework-5