首页 > 解决方案 > 为什么 ASP.NET MVC HttpFileCollection 会返回字符串数组而不是 HttpPostedFile 集合?

问题描述

我有一个 AngularJS + ASP.NET MVC 5 应用程序,我正在尝试实现单个文件上传。

在客户端,我有以下代码:

api.uploadFileV2 = function (alias, file, fnSuccess, fnError) {
    var formData = new FormData();
    formData.append(file.name, file);
    $http.post('/api/V2/Upload/' + alias, formData, {
        transformRequest: angular.identity,
        headers: { 'Content-Type': undefined }
    }).success(function (data) {
        if (fnSuccess)
            fnSuccess(data);
    }).error(function (data) {
        if (fnError)
            fnError(data);
    });
}

文件参数是通过单击按钮调用的函数传入的,当在 Chrome 和 Edge 中执行时,我可以看到文件参数实际上是一个文件对象。

回到服务器端,我有一个到控制器的路由,定义如下:

config.Routes.MapHttpRoute(
    name: "V2UploadApi",
    routeTemplate: "api/V2/Upload/{alias}/{id}",
    defaults: new { controller = "Upload", id = RouteParameter.Optional }
);

回到服务器端,我有我的 UploadController,其中定义了以下方法:

public JArray Upload(string Alias)
{
    JArray results = new JArray();
    try
    {
        HttpRequest r = HttpContext.Current.Request;
        HttpFileCollection c = r.Files;
        foreach (var item in r.Files)
        {
            string theType = item.GetType().Name;
        }

    }
    ...
}

注意:使用 Alias 参数的奇怪方法签名的原因是最终上传的文件将由 Powershell 脚本管理,该脚本的选择和安全级别取决于别名值。

执行 UploadController.Upload 方法后,我看到了我期望的 Alias 值。

我没有看到我的文件对象。所以var item没有像我预期的那样解析为HttpPostedFile类型,而是解析为字符串类型,因此变量"theType" 包含 "string" 而不是 "HttpPostedFile"。HttpFileCollection 实际上并不包含 HttpPostedFile 对象的集合,并且尝试将集合结果中的项目强制转换为 HttpPostedFile 类型会导致引发异常。

什么可能导致服务器端出现这种奇怪的行为,我能做些什么来纠正它?

像上传文件这样基本的东西不应该这么难,所以我一定遗漏了一些明显的东西——问题是我没有看到它。

标签: angularjsfile-uploadasp.net-mvc-5asp.net-web-api2

解决方案


因此,在另一个调试会话之后,我将代码更改为:

HttpRequest r = HttpContext.Current.Request;
HttpFileCollection c = r.Files;
foreach (string key in r.Files.Keys)
{
    var item = r.Files[key];
    string theType = item.GetType().Name;
}

这段代码不仅有效,而且还吸引了我的老式编码风格,即不懒惰地使用var将所有内容完全交给编译器。我错误地假设 HttpFileCollection 的枚举器返回(string)Key/(HttpPostedFile)Value对,但我错了。


推荐阅读