2014-10-28 72 views
0

我有一个名为ValidateFileAttribute的文件,用于验证图像上传的正确输入。就像这样:使用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; 
     } 

    } 

,这是模型的propertie:

[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小于1MB)我得到这个错误:

var file = value as HttpPostedFileBase; file is null。

谢谢

这是一个完整的视图:

<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 =“请选择一个PNG图像小于1MB“)]我可以上传图像。但ofcourse它必须与验证

我有现在这样的:

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; 
     } 

和propertie:

[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" }); 
     } 

这:

公众的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());

+0

也许你实际上没有上传f ILE。我没有看到表单元素,因此我不能说你是否正确地做了这件事。表单的内容类型应该是'multipart/form-data'。你调试了你的代码吗?你的属性中的'value'是否真的是'null'? – 2014-10-28 10:06:24

+0

感谢您的评论,我更新了我的文章 – 2014-10-28 10:12:59

+0

模型上的属性是一个'byte []',但验证器试图将值作为'HttpPostedFileBase'转换,你不能这样做,与您的模型类型兼容,即更改验证器以使用字节数组。 – 2014-10-28 10:14:53

回答

2

but ImageProfile is still null?? How can that be?

我看不出与name="ImageProfile"视图输入字段。所以这个属性是空的是正常的。所以,你可以通过固定该启动:

<input type="file" name="ImageProfile" class="filestyle" data-buttontext="Find file"> 

那么你应该知道的是,ASP.NET MVC默认模型联编知道如何该文件的输入转换为一个HttpPostedFileBase类型,而不是一个byte[]

因此,这将是您需要在您的视图模型来解决,接下来的事情:

[DisplayName("ImageProfile")] 
[ValidateFile(ErrorMessage = "Please select a PNG image smaller than 1MB")] 
public HttpPostedFileBase ImageProfile { get; set; } 

,明显反映在您的验证属性这一变化:

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; 
} 

终于摆脱这种文件参数在您的控制器行动,因为它不再使用:

[HttpPost] 
public ActionResult EditPhotos(UserProfile userprofile) 
{ 
    ... 
} 
+0

谢谢达林!为你的answare。请参阅我的上述编辑 – 2014-10-28 16:31:44

+0

我在方法中看到一些错误请参阅我的编辑文章 – 2014-10-28 16:34:53

+0

您的控制器操作应该将视图模型作为参数,而不是实际的EntityFramework模型。视图模型应该使用HttpPostedFileBase,并且在将它传递到数据库 – 2014-10-29 05:45:59