2

我正在为一个 B2B 应用程序构建一个简单的 CMS。用户可以上传/浏览图像,但这些图像存储在 IIS 之外(我的应用程序位于驱动器 C,图像存储在驱动器 D)。

我的计划是为页面文件创建一个自定义路由,然后简单地使用加载图像FileController

文件控制器:

public FilePathResult PageFiles(string fileName)
{
    var dir = Server.MapPath("/some_protected_area/gallery");
    var path = Path.Combine(dir, fileName);
    return File(path, "image/jpg");
}

自定义路线:

routes.MapRoute(
    null,
    "Files/PageFiles/{fileName}",
    new { controller = "File", action = "PageFiles", fileName = UrlParameter.Optional },
    new[] { "DemoApp.Web.Controllers" }
    );

当我访问时,http://localhost:58891/Files/PageFiles/image-1.jpg我得到 404。

详细错误信息:

Modeule: IIS Web Core
Notification: MapRequestHandler
Handler: StaticFile
Error code: 0x80070002

当我访问时:http://localhost:58891/Files/PageFiles?fileName=image-1.jpg一切正常,但我不想发送fileName查询字符串,并且fileName 必须包含扩展名(.jpg、.pdf 等)

我可以以某种方式禁用StaticFile自定义路由的处理程序吗?

任何帮助将不胜感激!

4

2 回答 2

8

我可以以某种方式禁用自定义路由的静态文件处理程序吗?

当然,只需将以下处理程序添加到<handlers>web.config 的部分:

<system.webServer>
    ...
    <handlers>
        ...
        <add 
            name="MyImageHandler" 
            path="Files/PageFiles/*" 
            verb="GET" 
            type="System.Web.Handlers.TransferRequestHandler" 
            preCondition="integratedMode,runtimeVersionv4.0" 
        />
    </handlers>
</system.webServer>

这个处理程序的作用是拦截所有请求Files/PageFiles/*并将它们传递给托管的 ASP.NET 管道以进行服务。这样他们就会达到预期的效果FilesController。如果没有此处理程序,IIS 会认为请求是针对静态文件的(因为它以 结尾.jpg)并完全绕过尝试直接提供文件的托管执行。

顺便Server.MapPath说一下,您在控制器操作中使用的此功能不适用于存储在 Web 应用程序文件夹之外的文件。

备注:您可能会看到其他建议您设置的响应,<modules runAllManagedModulesForAllRequests="true" />但我完全不建议您使用这种方法,因为这将使所有对所有静态文件的请求都通过托管管道,这可能会对您的应用程序产生负面的性能影响。仅对您要处理的路由启用此功能 ( Files/PageFiles/*) 效率更高。

于 2013-06-08T09:34:30.467 回答
2

几天前我在这里回答了类似的问题,但基本上是:

您的路径必须使用通配符{*fileName}

routes.MapRoute(
    null,
    "Files/PageFiles/{*fileName}",
    new { controller = "File", action = "PageFiles", fileName = UrlParameter.Optional },
    new[] { "DemoApp.Web.Controllers" }
    );

而且,要绕过 StaticFile 处理程序,您必须像这样更改 Web 配置:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />

顺便说一句,有一些答案建议您使用TransferRequestHandler而不是runAllManagedModulesForAllRequests,这是有效的方法,但无论如何您必须修复路线。

于 2013-06-08T09:34:22.987 回答