2014-10-28 69 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