文件夹名称中的空格突然导致IIS问题

时间:2014-04-23 19:44:14

标签: asp.net iis

问题

<a href='/assets/Roses%20are%20red/Violet%20are%20blue/I_love_you.pdf'>I Love You</a>

映射到(作为名为assets的网站中的虚拟目录):

D:\Digital Assets\Roses are red\Violets are blue\I_love_you.pdf

不适用于IIS v6和.NET 4.0的组合。

背景

它适用于IIS v6和.NET 2.0的组合。我们的测试还表明它可以与IIS v7和.NET 4.0一起使用。但是,我们的服务器当前正在运行Server 2003,因此我们对可以进行的升级有限制。

我们在带有.NET 4.0的Server 2003上运行IIS版本6。在我们的数据库中,我们有一个指向PDF文档的有用的相对链接列表。包含这些PDF文档的一些文件夹的名称中包含空格,例如“/ Roses为red / Violet为blue / I_love_you.pdf”。当它在页面上呈现时,我们最终会爱上你.pdf。

我在Global.asax中有代码可以快速验证PDF实际存在,如果没有,它会立即抛出404。此代码运行正常,并验证文件是否存在。

不幸的是,这些链接正在执行几个周期寻找文件(实际存在),然后抛出404或502.

为了进行测试,我们从服务器上的文件夹名称中删除了空格,并在没有%20的情况下直接尝试了链接。 PDF文档立即打开。

这刚开始发生在服务器上最近的.NET升级。有没有办法解决这个问题?

Global.asax中

Private ReadOnly _assetTails As New List(Of String) _
    (".pdf|.htm|.doc|.xls|.jpg|.ppt|.zip|.exe|.wmv|.msi|.tif|.swf|.mov|.mp4|.flv".Split("|"c).ToList())

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    Dim tail = IO.Path.GetExtension(Request.Url.Segments.ToList().Last()).ToLower()

....

    If _assetTails.Exists(Function(x)
                              Return tail.StartsWith(x)
                          End Function) Then
        Dim fullOrigionalPath As String = HttpContext.Current.Request.Url.ToString()
        Dim filename = Server.MapPath(Server.UrlDecode(Request.Url.AbsolutePath))
        If Not WebUtility.FileExists(fullOrigionalPath, filename) Then
            Dim sError = String.Format("File '{0}' not found", filename)
            Throw New HttpException(404, sError)
        End If
    End If

WebUtil.FileExists

Public Shared Function FileExists(ByVal urlOriginal As String, ByVal filename As String) As Boolean
    Dim logger As Logger = LogManager.GetCurrentClassLogger
    Try
        logger.Debug(String.Format("Does file '{1}' exist for '{0}'?", urlOriginal, filename))
        If File.Exists(filename) Then
            Return True
        Else
            Dim sError = String.Format("File '{0}' not found", filename)
            logger.Error(sError)
            Return False
        End If
    Catch ex As Exception
        logger.Error(ex.Message)
        Return False
    End Try
End Function

1 个答案:

答案 0 :(得分:1)

如果对IIS 6.0实例上的ASP.NET管道发出静态文件的请求,那么有人可能已经设置了通配符应用程序映射。我建议完全绕过ASP.NET管道来获取静态内容。这应该可以解除.NET版本之间的任何行为差异。它需要配置您的Web服务器。

Installing Wildcard Application Mappings (IIS 6.0)

首先,您需要通过查看IIS管理器找到应用程序的“标识符”:

enter image description here

请注意,此图片来自related post on Steven Sanderson's blog

要删除特定目录上的通配符映射,请打开命令提示符,切换到%SystemDrive%\ inetpub \ AdminScripts c:\ Inetpub \ AdminScripts,然后运行:

adsutil.vbs SET /W3SVC/[identifer]/root/Content/ScriptMaps ""

将[identifier]替换为您的应用程序的“标识符”编号。此外,您可以将“内容”替换为任何其他目录的路径。现在,您的/ Content文件夹现在将绕过通配符映射,其文件将由IIS本地提供。

如果您无法为整个应用程序执行此操作,则可以为内容设置虚拟目录,并关闭该目录的通配符映射。

另一种选择是自己拦截对这些文件的请求并直接流回其内容,而不是依赖于ASP.NET管道的默认行为。