代码之家  ›  专栏  ›  技术社区  ›  Paul Gibson

MVC.net让视图上传图像时出现视图和控制器问题

  •  0
  • Paul Gibson  · 技术社区  · 3 年前

    通过使用具有 HttpPostedFileBase 属性绑定到视图,这样表单只需要一个post方法即可上传图像,然后将实体添加到数据库中。

    这是表单标签:

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

    以及绑定到视图模型属性的视图控件(默认情况下,如果名称匹配,则会发生这种情况,在我的情况下,属性为 Http发布的文件库 文件:

    <input type="file" name="file" />
    

    这比我在下面所走的道路要容易得多,我试图为一个视图有两个不同的后期操作(从我读到的所有内容来看,这应该是可能的,但我认为我的问题是试图在表单中有一个表单):

    我的Lesson控制器有两个post方法,可以调用:

    第一步是创建一个新课程:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create(Lesson lesson)//, WebImage Photo)
        {
            if (ModelState.IsValid && Request.Form["Create"]!=null) 
                //Request.Form check because the image file function is calling back to this handler
                //Once that is sorted out the check can be removed and simply use ModelState.IsValid
            {
                db.Lessons.Add(lesson);
                await db.SaveChangesAsync();
                return RedirectToAction("Index");
            }
            ViewBag.DivID = new SelectList(db.Divisions, "ID", "DivName", lesson.DivID);
            ViewBag.ProjectID = new SelectList(db.Projectinformations, "ID", "Code", lesson.ProjectID);
            ViewBag.PeopleID = new SelectList(db.Peoples, "ID", "Firstname", lesson.PeopleID);
            return View(lesson);
        }
    

    在页面上,这是一个表单(缩写),带有调用控制器的提交按钮。Create()操作:

    @using (Html.BeginForm())
    {
    @Html.AntiForgeryToken()
     //. . . for each Lesson property there is a form group with @Html Label
     //@Html.EditorFor, etc. and then at the bottom is this:
    
            <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" name="Create" class="btn btn-default" />
            </div>
        </div>
    

    图像路径字段是主表单的一部分,我为它的文本框等留下了生成的代码。这是我试图插入调用不同控制器操作的图像上传的表单部分:

        <div class="form-group">
            <div class="col-md-10">
                <form action="UploadImage" name="ImageFileForm" id="imageForm" method="post" enctype="multipart/form-data">
                    <input type="file" name="file" />
                    <input type="submit" value="OK" name="OK" />
                </form>
            </div>
            @Html.LabelFor(model => model.Image, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Image, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Image, "", new { @class = "text-danger" })
            </div>
        </div>
    

    这是UploadImage的控制器操作

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult UploadImage(HttpPostedFileBase file)
        {
            string imagePath ="";
            if (file != null)
            {
                var newFileName = Path.GetFileName(file.FileName);
                imagePath = @"LessonsLearnedImages\" + newFileName;
                file.SaveAs(@"~\" + imagePath);
            }
            ViewBag.DivID = new SelectList(db.Divisions, "ID", "DivName", lesson.DivID);
            ViewBag.ProjectID = new SelectList(db.Projectinformations, "ID", "Code", lesson.ProjectID);
            ViewBag.MOAPeopleID = new SelectList(db.MOApeoples, "ID", "Firstname", lesson.MOAPeopleID);
            ViewBag.Image = imagePath;
            return View();
        }
    

    然而,当我按下ImageUpload按钮时,会调用控制器Create(表单默认值)函数。我可能会使用控制器中的Create操作来执行Request.Form检查的所有操作,但在向其添加HttpPostedFileBase参数时,这对我来说失败了。

    0 回复  |  直到 3 年前
        1
  •  0
  •   OJ Raqueño    3 年前

    对于图像上传,有两件事需要保存。第一部分是保存实际图像,例如保存到计算机上的文件夹中。第二部分是保存有关图像的信息,例如将其完整路径保存在数据库中。完成这两个部分非常重要,这样您以后才能检索图像。

    捕获图像(或一般上传的文件)的一种方法是使用 HttpPostedFileBase 作为参数的类型:

    [HttpPost]
    public async Task<ActionResult> Upload(HttpPostedFileBase myFile)
    {
        // myFile contains several properties which you need to be able to save the file
    }
    

    这个 myFile 参数有几个需要保存的属性。例如,您上传图像的路径以及您可以提取为 byte[] 。

    网页上的相应表格,被删减为基本部分,将是:

    <form action="Upload" method="post" enctype="multipart/form-data">
        <input type="file" name="myFile" />
        <input type="submit" value="Click me to upload" />
    </form>
    

    您需要确保以下排列,以便调用正确的控制器操作:

    • 表单的方法应与控制器方法的谓词匹配( post 形式对应于 HttpPost 在控制器中)
    • 表单的操作应与控制器方法的名称匹配( Upload 在这种情况下)
    • 输入的名称应与控制器方法的参数的名称匹配( 我的文件 在这种情况下)

    您还需要确保enctype multipart/form-data 为了 我的文件 参数实际具有值。如果不是,则可以执行正确的控制器方法,但参数可能为null。

    毕竟,你应该有一个合适的 我的文件 可用于保存其属性的参数。例如,保存图像后,可以将其完整路径存储在 ImagePath 您的中的列 Lessons 桌子

    正如您所提到的,一旦控制器方法完成执行,图像(以及其他任何内容)就会丢失。但这没关系,因为我们已经将图像和图像路径保存在持久存储中了。若要在以后检索图像,只需查看相关的课程即可。例如,假设您有 Model 对象,该对象对应于您从数据库中获得的课程,显示图像可能如下所示:

    <img src="@Model.ImagePath" />
    

    编辑

    似乎您想一次保存创建页面上的多个字段,而图像文件只是其中一个字段。在这种情况下,控制器上只需要一个方法,页面上只需要单个表单元素。

    要捕获文件,请添加 Http发布的文件库 作为课程视图模型中的特性,例如:

    public class Lesson
    {
        public HttpPostedFileBase File { get; set; }
    }