问题
<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
答案 0 :(得分:1)
如果对IIS 6.0实例上的ASP.NET管道发出静态文件的请求,那么有人可能已经设置了通配符应用程序映射。我建议完全绕过ASP.NET管道来获取静态内容。这应该可以解除.NET版本之间的任何行为差异。它需要配置您的Web服务器。
Installing Wildcard Application Mappings (IIS 6.0)
首先,您需要通过查看IIS管理器找到应用程序的“标识符”:
请注意,此图片来自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管道的默认行为。