上传图像并在本地存储,在db中保存文件名,在视图中显示MVC 5

时间:2017-03-29 20:52:41

标签: c# asp.net-mvc entity-framework

花了很多时间浏览类似的文章,寻找这个问题的答案,以下是其中一些:

1Link,(无法显示超过2个链接,但我有一堆链接)

最相关的 8 Link但该项目无效

但是经过这些例子之后我还是无法解决这个问题。目前我的项目没有图像工作,我可以CRUD新文章页面并删除它。但现在我需要添加图像。 首先,我需要一个图像作为一个类的一部分(我正在创建一个带有一些标题,简短描述,文本正文和图像的新文章)这里是我想出的模型,这是非工作代码。因为我想将文件链接存储到db所以我想我需要创建新的变量ImagePath

namespace PhClub.Models
{
    public class Media
    {
        public int Id { get; set; }

        public string title { get; set; }
        public string description { get; set; }
        [Required, StringLength(2048), DataType(DataType.MultilineText)]   
        public string body { get; set; }
        public string ImagePath { get; set; }
    }
}

接下来我需要添加创建表单来获取文件名来上传它。这是创建视图代码段

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

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

        <div class="form-group">
            @Html.LabelFor(model => model.title, "Title", new { @class = "control-label col-md-2" })          
            <div class="col-md-10">
                @Html.EditorFor(model => model.title)
                @Html.ValidationMessageFor(model => model.title)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.description, "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.body,  "Media",new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.body)
                @Html.ValidationMessageFor(model => model.body)
            </div>
        </div>
        **<div class="form-group">
            File name
            <div class="uploadfile">
                @Html.TextBoxFor(model => model.file, new { type = "file" })
                @Html.ValidationMessageFor(model => model.file)
                <input type="submit" value="Submit" />
            </div>
        </div>**

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Создать" class="btn btn-default" />
            </div>
        </div>
    </div>
}

然而,我有两个不确定因素: 1.我已经在Controller中有一个Create方法,它由EF为我生成:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,title,description,body")] Media media)
        {
            if (ModelState.IsValid)
            {
                db.Medias.Add(media);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(media);
        }

但我需要以某种方式将它以某种方式与此方法集成(我从其中一个例子中选择了这个)

   [HttpPost]
    public ActionResult FileUpload(Media mRegister)
    {
        //Check server side validation using data annotation
        if (ModelState.IsValid)
        {
            //TO:DO
            var fileName = Path.GetFileName(mRegister.file.FileName);
            var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
            mRegister.file.SaveAs(path);
            ViewBag.Message = "File has been uploaded successfully";
            ModelState.Clear();
        }
        return View();
    }

我不能有两个同名的方法 - 一方面创建不同的东西另一方面我不能给它不同的名字,因为我不需要其他视图,它需要在创建时显示如果我明白这里发生了什么,请查看。 2.中学 - 我需要有两个按钮吗?一个用于上传图像,一个用于创建对象?

最后,我需要在Media视图中以某种方式将图像显示为文章的一部分。目前它看起来像那样

    <h2>@Model.title</h2>
    <br>

    <div class="media">
        <p>
            <strong>@Html.Raw(Model.title)</strong>
        </p>
        <p>
            @Html.Raw(Model.description)
        </p>
        <p>
            @Html.Raw(Model.body)
        </p>
    </div>
   <div style ="float:right margin: 0px; 0px; 15px; 15px;">
          @Html.Raw(Model.file)
   </div>

从这里我迷失了。我需要将该图像放在某个位置,但不知道如何。在其他示例中,人们为文件创建了一堆其他类。我需要它吗?这是最简单的方法吗?我知道我并不是第一个提出这个问题的人,但我真的可以帮助你了。

2 个答案:

答案 0 :(得分:2)

你的代码对我来说有点混乱。在第二个示例中,您使用的是file属性。但是你的班级没有那个!!!

一个建议 :在编写C#类和be consistent时尝试使用PascalCasing

理想情况下,您应该为视图创建视图模型

public class MediaVm
{
   public string Title { get; set; }
   public string Body { get; set; }
   public HttpPostedFileBase Image { set; get; } 
}

现在您的视图强烈输入此视图模型

@model MediaVm
@using (Html.BeginForm("Create", "Medias", FormMethod.Post,
                                                new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(false)
    @Html.TextBoxFor(s=>s.Title)
    @Html.TextBoxFor(s=>s.Body)    
    @Html.TextBoxFor(model => model.Image, new { type = "file" })    
    <input type="submit" />
}

现在,在您的httppost操作方法中,使用与参数相同的视图模型,读取Image属性值,使用唯一名称保存到磁盘并在表中保存该唯一文件名。我们将把文件保存到磁盘的代码移动到另一个方法,可以根据需要从其他方法中使用。

[HttpPost]
public ActionResult Create(MediaVm model)
{
  if (ModelState.IsValid)
  {
      var fileName = SaveAndReturnFileName(model.Img);
      var m = new Media { title = model.Title, body, model.Body};
      m.ImagePath = fileName;
      db.Medias.Add(m);
      db.SaveChanges();
      return RedirectToAction("Index");
  }
  return View(model);
}
public string SaveAndReturnFileName(HttpPostedFileBase file)
{
    if (file == null)
        return null;

    var fileName = Path.GetFileName(file.FileName);
    string randomFileName = Path.GetFileNameWithoutExtension(fileName) +
                        "_" +
                        Guid.NewGuid().ToString().Substring(0, 4) 
                            + Path.GetExtension(fileName);
    var path = Path.Combine(Server.MapPath("~/Content/Upload/"), randomFileName);
    file.SaveAs(path);
    return randomFileName;
}

您应该可以像下面的网址一样访问图片

yourSiteName/Content/Upload/theRandomImageNameWeSavedInTable

答案 1 :(得分:0)

好的,经过进一步的研究,我设法让它发挥作用。 This is how it looks

我的班级

public class Media
{
    public int Id { get; set; }

    public string title { get; set; }
    public string description { get; set; }
    [Required, StringLength(2048), DataType(DataType.MultilineText)]   
    public string body { get; set; }
    public string ImagePath { get; set; }


}

控制器方法

public ActionResult Create([Bind(Include = "Id,title,description,body")] Media media, HttpPostedFileBase file)
        {
            if (ModelState.IsValid)
            {
                if (file != null)
                {
                    file.SaveAs(HttpContext.Server.MapPath("~/Images/")
                                                          + file.FileName);
                    media.ImagePath = file.FileName;
                }
                db.Medias.Add(media);
                db.Medias.Add(media);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(media);
        }

上传图片的代码

 <fieldset>
            <legend>Image</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.ImagePath)
            </div>
            <div class="editor-field">
                <input id="ImagePath" title="Upload a product image"
                       type="file" name="file" />
            </div>
 </fieldset>

显示最终结果的媒体视图

<div class="media">
    <div style="float: right; margin: 0px 0px 15px 15px; height: 300px; width:450px">
        <div id="imageContainer">
            @*@Html.Raw(Model.ImagePath)*@
            <img src="~/Images/@Html.Raw(Model.ImagePath)" />
        </div>
    </div>
    <p>
        <strong>@Html.Raw(Model.title)</strong>
    </p>
    <p>
        @Html.Raw(Model.description)
    </p>
    <p>
        @Html.Raw(Model.body)
    </p>
</div>

和css格式化以将图像调整为div尺寸

div > img {

  width: auto;
  height : auto;
  max-height: 100%;
  max-width: 100%;
}

我用来解决问题的链接是Uploading/Displaying Images in MVC 4

谢谢大家。