带有模型的 mvc 上传文件 - 第二个参数发布的文件为空
Posted
技术标签:
【中文标题】带有模型的 mvc 上传文件 - 第二个参数发布的文件为空【英文标题】:mvc upload file with model - second parameter posted file is null 【发布时间】:2014-03-07 18:35:02 【问题描述】:我有一个带有 1 个字符串属性的简单模型,我在一个简单的视图上呈现它。
视图如下所示:
@using (html.BeginForm("UploadFile", "Home", FormMethod.Post, new encType="multipart/form-data" ))
@Html.TextBoxFor(m => m.FirstName)
<br /><br />
<input type="file" name="fileUpload" /><br /><br />
<input type="submit" value="submit me" name="submitme" id="submitme" />
控制器是这样的:
[HttpPost]
public ActionResult UploadFile(UploadFileModel model, HttpPostedFileBase file)
// DO Stuff
return View(model);
现在,当我提交时,模型确实被填充,但第二个参数 HttpPostedFileBase 为空。但是,在执行 Request.Files 时 - 它似乎确实显示正在发布的请求中有一个文件。 我如何才能真正获得要绑定的第二个参数?
【问题讨论】:
绑定是按名称进行的,由于您在输入标记上有name="fileUpload"
,因此您的操作方法的第二个参数应命名为相同的名称,即HttpPostedFileBase fileUpload
。
【参考方案1】:
为什么不像这样将上传的文件添加到您的模型中:
public class UploadFileModel
public UploadFileModel()
Files = new List<HttpPostedFileBase>();
public List<HttpPostedFileBase> Files get; set;
public string FirstName get; set;
// Rest of model details
然后将您的视图更改为:
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new encType="multipart/form-data" ))
@Html.TextBoxFor(m => m.FirstName)
<br /><br />
@Html.TextBoxFor(m => m.Files, new type = "file", name = "Files" )<br /><br />
<input type="submit" value="submit me" name="submitme" id="submitme" />
然后您的文件将按如下方式回传:
public ActionResult UploadFile(UploadFileModel model)
var file = model.Files[0];
return View(model);
【讨论】:
有趣。这行得通。谢谢!但是为什么它不会绑定到第二个参数仍然没有意义。不过我想要一个解释。 只是在等待它让我接受答案 - 全部完成。我同意你的观点,VM 方法。只是......令人难以置信为什么它不会绑定第二个参数。 为什么使用 HttpPostedFileBase 而不是 HttpPostedFile? 参考 m.Files.Files 不正确。提交编辑 需要添加 HTML5 多个属性,如果你想选择多个具有相同输入控件的文件@Html.TextBoxFor(m => m.Files, new type = "file", multiple = "multiple", name = "Files" )
【参考方案2】:
为了处理单个文件输入,您可以在 ViewModel 中定义 HttpPostedFileBase
属性:
public class SomeModel()
public SomeModel()
public HttpPostedFileBase SomeFile get; set;
然后按如下方式实现:
查看:
@model SomeModel
@using (Html.BeginForm(
"Submit",
"Home",
FormMethod.Post,
new enctype="multipart/form-data" ))
@Html.TextBoxFor(m => m.SomeFile, new type = "file" )
<input type="submit" value="Upload"
name="UploadButton" id="UploadButton" />
控制器:
[HttpPost]
public ActionResult Submit(SomeModel model)
// do something with model.SomeFile
return View();
如果您需要处理多个文件,您可以:
创建多个属性并分别实现它们,就像上面的一样; 将public HttpPostedFileBase SomeFile
属性更改为public List<HttpPostedFileBase> SomeFiles
之类的属性,然后跨越多个@Html.TextBoxFor(m => m.SomeFile, new type = "file" )
控件以将它们全部包含在该列表中。
如果您需要更多信息,请查看我在该主题上写的 this blog post。
【讨论】:
【参考方案3】:把你的名字 file
改成 fileUpload
和 enctype
就可以了
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new enctype="multipart/form-data" ))
@Html.TextBoxFor(m => m.FirstName)
<br /><br />
<input type="file" name="fileUpload" /><br /><br />
<input type="submit" value="submit me" name="submitme" id="submitme" />
[HttpPost]
public ActionResult UploadFile(UploadFileModel model, HttpPostedFileBase fileUpload)
// DO Stuff
return View(model);
【讨论】:
@Ahmedilyas 我不知道为什么它不适合你。它完全适合我。 这种方法是我一直在寻找的,直接的方法,我有问题的解决方案中缺少的部分是 BeginForm 中的 "enctype="multipart/form-data" " :-/。【参考方案4】:或者,(如果可以接受)从模型中删除文件的 [Required] 验证注释并在 Controller 操作中检查文件,如果找不到则添加错误:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ActionWithFileUpload(ViewModel viewModel)
if (ModelState.IsValid)
if (Request.Files.Count > 0)
var postedFile = Request.Files[0];
if (postedFile != null && postedFile.ContentLength > 0)
string imagesPath = HttpContext.Server.MapPath("~/Content/Images"); // Or file save folder, etc.
string extension = Path.GetExtension(postedFile.FileName);
string newFileName = $"NewFileextension";
string saveToPath = Path.Combine(imagesPath, newFileName);
postedFile.SaveAs(saveToPath);
else
ModelState.AddModelError(string.Empty, "File not selected.");
return RedirectToAction("Index"); // Or return view, etc.
【讨论】:
以上是关于带有模型的 mvc 上传文件 - 第二个参数发布的文件为空的主要内容,如果未能解决你的问题,请参考以下文章