MVC:如何将文件上传和其他表单字段发布到一个操作

Posted

技术标签:

【中文标题】MVC:如何将文件上传和其他表单字段发布到一个操作【英文标题】:MVC: How to post File Upload and other form fields to one action 【发布时间】:2011-07-06 04:01:39 【问题描述】:

我正在创建一个带有DocumentController 的文档库应用程序,它需要上传库中每个文档的缩略图。我想将“文件上传”字段与其他字段(标题、描述、CategoryId 等)保持在同一个创建/编辑表单上。 问题是我不确定是否可以混合或嵌套

的表单标签
html.BeginForm("Create", "Document", FormMethod.Post, enctype = "multipart/form-data")

Html.BeginForm()

我的看法如下:

 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Publications.WebUI.Models.DocumentEditViewModel >" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <fieldset>
        <legend>Edit
            <%=  Html.Truncate(Model.Document.Title, 50)%></legend>
        <%= Html.ValidationSummary(false) %>
        <% using (Html.BeginForm())
            %>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.Title) %>
        </div>
        <div class="editor-field">
            <%= Html.HiddenFor(model => model.Document.DocumentId ) %>
            <%= Html.ValidationMessageFor(model => model.Document.Title) %>
            <%= Html.TextBoxFor(model => model.Document.Title)%>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.DocumentUrl)%>
        </div>
        <div class="editor-field">
            <%= Html.ValidationMessageFor(model => model.Document.DocumentUrl)%>
            <%= Html.TextBoxFor(model => model.Document.DocumentUrl)%>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.Description)%>
        </div>
        <div class="editor-field">
            <%= Html.ValidationMessageFor(model => model.Document.Description)%>
            <%= Html.TextAreaFor(model => model.Document.Description) %>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.ThumbnailUrl )%>
        </div>
        <div class="editor-field">
            <% using (Html.BeginForm("Create", "Document",
                    FormMethod.Post, new  enctype = "multipart/form-data" ))
               %>
            <%= Html.ValidationMessageFor(model => model.Document.ThumbnailUrl )%>
            <input name="uploadFile" type="file" />
            <%  %>
        </div>
        <div class="formActions">
            <div class="backNav">
                <%= Html.ActionLink("< Back to List", "Index") %>
            </div>
            <div class="submit">
                <input type="submit" value="Save" />
            </div>
            <%  %>
        </div>
    </fieldset>
</asp:Content>

我的控制器只使用 Document 模型和 HttpPostedFileBase 并尝试将文件上传到服务器并将 Document 保存到存储库

 [HttpPost]
 public ActionResult Create(Document document, HttpPostedFileBase uploadFile)
 

     if (ModelState.IsValid)
     
         //Process file upload
         //Update repository

      

       return View("List");
  

所以我想知道是否可以在同一操作上进行文件上传和更新存储库,以及我应该如何构建我的视图以促进这一点。

【问题讨论】:

我认为你的代码是正确的。:-) 注意任何有示例问题的人:原始问题代码应该可以正常工作,只需要添加到您的表单中的一件事是enctype = "multipart/form-data" 【参考方案1】:

我看过 Steve Sanderson 的好书(Pro ASP.NET MVC 2 Framework),他的 Sports Store 示例应用程序有一个文件上传表单,其中有标准表单元素与文件上传“multipart/form-data”混合元素。所以看起来 multipart 类型足以满足页面上的所有表单元素。虽然上传的图像保存在数据库中,但我确信我可以在同一个操作中执行 file.SaveAs()。谢谢桑德森先生。希望你不介意我复制你的代码...

查看

    <asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h1>Edit <%= Model.Name %></h1>

    <% using (Html.BeginForm("Edit", "Admin", FormMethod.Post, 
                             new  enctype = "multipart/form-data" ))  %>
        <%= Html.Hidden("ProductID") %>
        <p>
            Name: <%= Html.TextBox("Name") %>
            <div><%= Html.ValidationMessage("Name") %></div>
        </p>
        <p>
            Description: <%= Html.TextArea("Description", null, 4, 20, null) %>
            <div><%= Html.ValidationMessage("Description") %></div>
        </p>
        <p>
            Price: <%= Html.TextBox("Price") %>
            <div><%= Html.ValidationMessage("Price") %></div>
        </p>
<p>
    Category: <%= Html.TextBox("Category") %>
    <div><%= Html.ValidationMessage("Category") %></div>
</p>
<p>
    Image:
    <% if(Model.ImageData == null)  %>
        None
    <%  else  %>
        <img src="<%= Url.Action("GetImage", "Products", 
                                 new  Model.ProductID ) %>" />
    <%  %>
    <div>Upload new image: <input type="file" name="Image" /></div>                
</p>

<input type="submit" value="Save" /> &nbsp;&nbsp;
        <%=Html.ActionLink("Cancel and return to List", "Index") %>
    <%  %>
</asp:Content>

控制器

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Product product, HttpPostedFileBase image)
    
        if (ModelState.IsValid) 
            if (image != null) 
                product.ImageMimeType = image.ContentType;
                product.ImageData = new byte[image.ContentLength];
                image.InputStream.Read(product.ImageData, 0, image.ContentLength);
            
            productsRepository.SaveProduct(product);
            TempData["message"] = product.Name + " has been saved.";
            return RedirectToAction("Index");
        
        else // Validation error, so redisplay same view
            return View(product);
    

【讨论】:

以上是关于MVC:如何将文件上传和其他表单字段发布到一个操作的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot App 中使用 Jquery 和 FormData 提交表单字段并上传 File 到 Spring MVC Controller

在vue.js中上传照片和其他表单内容一起使用。

需要使用角度的mat表单字段上传文件

使用 MVC 4 和 Ajax 上传文件

如何使用 Django 将表单/字段内容上传到 IPFS 节点?

多字段的 MVC 表单验证