尝试使用ASP.NET MVC上传文件

5

我正在尝试使用ASP.NET MVC上传文件。

以下代码完美地工作:

// Read in the image data.
byte[] binaryData = null;
HttpPostedFileBase uploadedFile = Request.Files["ImageFileName"];
if (uploadedFile != null &&
    uploadedFile.ContentLength > 0)
    {
        binaryData = new byte[uploadedFile.ContentLength];
        uploadedFile.InputStream.Read(binaryData, 
                                      0,
                                      uploadedFile.ContentLength);
    }

但我试图使用在“futures”程序集中找到的新的FileCollectionModelBinder
我发现这两篇博客文章这里这里解释了该怎么做。我按照这些说明操作,但是没有成功——file对象总是null
以下是我的方法。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "Subject, Content")]
                           Post post, 
                           HttpPostedFileBase file)
{
    UpdateModel(post);
    ...
}

请注意,我正在尝试上传文件并上传一些帖子信息到一个Post对象中。
有人可以提出任何建议吗?
为了记录,我已经在global.asax.cs中连接了ModelBinder。我也确保了表单是带有添加enctype的post:-
<form method="post" enctype="multipart/form-data" action="/post/create">
4个回答

10

完全不可能 :(

我找到了那个答案,但它相当糟糕。

我必须确保参数NAME与输入类型为“file”的元素的Id/Name值完全相同!!!(不确定是元素值还是两者都...我没有检查那一部分)。

所以这就是答案。

HTML输入元素。(请注意Id/Name的值)

<input type="file" id="imageFileName" name="imageFileName" class="upload" />

控制器方法

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "Subject, Content")]Post post,
    HttpPostedFileBase imageFileName)
{
...
}

天啊!


你的视图是否包含与你的Post模型相关的其他HTML元素?我有一个带有ImagePath属性和其他属性的模型。在视图中,除了该属性的<input type="file" id="imagePath" name="imagePath" />之外,还有我的模型的所有HTML元素。您只需将强类型模型与HttpPostedFileBase一起放入控制器中,就可以访问上传的文件并设置ImageFilePath了吗?不确定您是否可以在post操作中设置模型? - Jon
1
这有什么不好的呢?否则ASP.NET MVC怎么能将上传的文件绑定到你的操作方法中的特定参数呢? - bzlm
1
为什么不只取ID(通常是唯一的值)呢?这种方法很糟糕,因为它要求两个属性具有相同的值。 - Pure.Krome
1
Id 没有被提交,只有名称… 这就是为什么模型绑定器无法使用它。 - bzarah
这是浏览器向服务器发送数据的基本属性。它们使用“名称”属性而不是“ID”属性。这与MVC无关。 - Chris Rogers
我正在编写一个Python脚本,将文件发布到IIS / ASP.NET MVC应用程序中,这非常有帮助 - 谢谢。使用requests库,我不得不创建一个字段变量,该变量与服务器上的HttpPostedFileBase变量的C#变量名称完全相同。我注意到这个区别是因为在我这样做之前,System.Web.HttpContext.Current.Request.Files有文件,但HttpPostedFileBase变量仍然为空。 - Chris Townsend

5

请记得你还需要像这样打开表单:

<form enctype="multipart/form-data" ...

是的 - 当然可以..而且我有那个。 - Pure.Krome
刚刚和一篇文章斗争了好久。我已经对了第一部分(名称和ID),但我错过了表单属性!谢谢你的提醒。 - Simon Parker

1

不确定这是否与问题相关,但我刚找到了一种方法,在复杂对象中使HttpPostedFileBase的模型绑定工作。不幸的是,我不得不对ASP.NET MVC源代码进行更改,因此并非所有人都适用。

在System.Web.Mvc.ValueProviderDictionary.PopulateDictionary()中,值提供程序正在使用Request.Form、Request.QueryString和RouteData的内容填充,但不包括Request.Files。添加以下行以“修复”此问题(我说“修复”,因为ASP.NET MVC团队一开始可能有原因没有这样做)。

HttpFileCollectionBase files = ControllerContext.HttpContext.Request.Files;
if (files != null)
{
    string[] keys = files.AllKeys;
    foreach (string key in keys)
    {
        HttpPostedFileBase file = files[key];
        ValueProviderResult result = new ValueProviderResult(file, file.FileName, currentCulture);
        AddToDictionaryIfNotPresent(key, result);
    }
}

哦,那很有趣。我想听一些来自MVC团队的想法... Phil?Eilon?有人吗? - Pure.Krome

0
在过去的一周里,我一直在为我的MVC项目构建一个上传/文件管理系统。我的最初尝试是使用multipart文件值发布附加的帖子数据,但由于时间限制,这证明太困难了。现在我的方法是创建“相应记录”,以便文件/图像可以“附加”(就像在我的情况下一样),然后在记录存在后上传(“附加”)文件/图像。
例如:1)创建事件记录,2)使用上传控件附加图像
我接收multipart post的操作使用了Hanselman's post中的概念。
我不能说我已经尝试过用于文件的内置复杂类型绑定(HttpPostedFileBase),但我建议它会比我目前的解决方案更复杂,因为从阅读Hanselman上面写的文章中,我了解到Request中返回的文件集合只是一个松散类型的集合。
我建议坚持你最初的代码,并尝试使其更安全地满足你的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接