【问题标题】:Upload image included in MVC model上传包含在 MVC 模型中的图像
【发布时间】:2013-12-25 03:26:06
【问题描述】:

我有以下型号:

public class Photo
{
    public int PhotoId { get; set; }
    public byte[] ImageData { get; set; }
    public DateTime DateUploaded { get; set; }
    public string Description { get; set; }
    public bool IsActive { get; set; }

}

我希望用户能够输入照片的详细信息,然后将模型发布到控制器。我的控制器动作如下:

[HttpPost]
    public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
    {
        if (ModelState.IsValid)
        {
            photo.DateUploaded = DateTime.Now;
            _context.Photos.Add(photo);
            _context.SaveChanges();

            return RedirectToAction("Index");
        }
        //we only get here if there was a problem
        return View(photo);
    }

我的看法如下:

@using (Html.BeginForm()) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Photo</h4>
    <hr />
    @Html.ValidationSummary(true)

    <div class="form-group">
        @Html.LabelFor(model => model.ImageData, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <input type="file" name="uploadImages" class="input-files" />
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.DateUploaded, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.DateUploaded)
            @Html.ValidationMessageFor(model => model.DateUploaded)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.IsActive, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.IsActive)
            @Html.ValidationMessageFor(model => model.IsActive)
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

视图显示正常,允许用户从本地磁盘中选择文件并输入其他模型详细信息。 我的问题是,虽然模型已发布到控制器上,但描述、日期和 IsActive 标志已填充好 - 图像数据为空。

谁能告诉我我需要更改什么,以便将照片的字节数组包含在发布到控制器的模型中?

【问题讨论】:

    标签: asp.net-mvc image post bytearray


    【解决方案1】:

    您视图中的文件输入名称为uploadImages。我在您的视图模型中看不到具有此名称的属性。您似乎有一些 ImageData 属性,它是一个字节数组,但您的视图中似乎没有具有此名称的相应输入字段。

    这解释了为什么你会得到 null。您可以通过遵守约定来完成这项工作。因此,例如,如果您打算在视图中有这样一个输入字段:

    <input type="file" name="uploadImages" class="input-files" />
    

    然后确保您的视图模型上有一个同名的属性。当然还有HttpPostedFileBase

    public HttpPostedFileBase UploadImages { get; set; }
    

    在您看来,请确保您设置了正确的 multipart/form-data 内容类型:

    @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        ...
    }
    

    您可能希望通过following blog post 更好地熟悉如何在 ASP.NET MVC 中上传文件的基础知识。我还写了一个similar answer here,你可以参考一下。

    因此,一旦在视图模型中添加带有 UploadImages 名称的 HttpPostedFileBase 属性,您就可以调整控制器操作以读取字节数组并将其存储为您的 ImageData 属性:

    [HttpPost]
    public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
    {
        if (ModelState.IsValid)
        {
            photo.DateUploaded = DateTime.Now;
            photo.ImageData = new byte[photo.UploadImages.ContentLength];
            photo.UploadImages.Read(photo.ImageData, 0, photo.ImageData.Length);
    
            _context.Photos.Add(photo);
            _context.SaveChanges();
    
            return RedirectToAction("Index");
        }
    
        //we only get here if there was a problem
        return View(photo);
    }
    

    现在请记住,这是一个绝对糟糕的解决方案。永远不要在现实世界的应用程序中这样做。在正确设计的应用程序中,您将拥有一个视图模型,您的控制器操作将作为参数。您永远不会直接使用自动生成的 EF 模型作为控制器操作的参数。您将拥有一个带有 HttpPostedFileBase 属性的视图模型,该属性将映射到您的域模型。

    因此,在设计合理的应用程序中,您将拥有一个 PhotoViewModel 视图模型类,您的控制器操作将执行该类。

    【讨论】:

    • 另一个很好的答案感谢达林。我将创建一个专用的视图模型。我为此解决方案使用了一个存储库项目,但我发现额外的抽象层确实使我的 moq'd 单元测试变得复杂。
    • 不应该是这样的:photo.UploadImages.InputStream.Read
    【解决方案2】:

    改变这一行:

    @using (Html.BeginForm()) 
    

    到这里:

    @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
    

    然后改变:

    <input type="file" name="uploadImages" class="input-files" />
    

    收件人:

    <input type="file" name="ImageData" class="input-files" />
    

    然后改变这一行:

     public byte[] ImageData { get; set; }
    

    到这里:

     public HttpPostedFileBase ImageData { get; set; }
    

    最后,使用类似这样的代码将图像读入字节数组:

     var bs = new byte[ImageData.ContentLength];
     using (var fs = ImageData.InputStream)
     {
         var offset = 0;
         do
         {
             offset += fs.Read(bs, offset, bs.Length - offset);
         } while (offset < bs.Length);
     }
    

    【讨论】:

      【解决方案3】:

      查看:

      @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
      {
         ...
         <input type="file" id="ImageFile" name="ImageFile" .../>
         ...
      }
      

      控制器:

      [HttpPost]
      public ActionResult Create(Photo photo, HttpPostedFileBase ImageFile)
      {
          byte[] buf = new byte[ImageFile.ContentLength];
          ImageFile.InputStream.Read(buf, 0, buf.Length);
          photo.ImageData = buf;
          ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        • 2012-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-09
        • 2012-05-11
        相关资源
        最近更新 更多