我正在开发一个我用ASP.Net构建的网站,我只是稍微熟悉一下。其中一个页面允许链接到文档(word或pdf),当单击该文档时,会提示用户保存或打开文件,但不会显示文件的真实路径。这样它就可以防止用户将url粘贴到文件 - 该链接指向检查有效会话的aspx文件,然后检索该文件。
无论如何,因为有很多遗留代码,我需要用一堆静态htm文件做这个,但是这些文件需要显示而不是提示用户保存它们,这就是现在发生的事情。我尝试将内容类型更改为应用程序/文本,应用程序/ html,文本/ html等,但这不起作用,然后尝试添加内容处置内联的响应标头。当我这样做,构建,并尝试链接到该文件时,我得到了几个运行时异常:
[FormatException: Input string was not in a correct format.]
Microsoft.VisualBasic.CompilerServices.Conversions.ParseDecimal(String Value, NumberFormatInfo NumberFormat) +206
Microsoft.VisualBasic.CompilerServices.Conversions.ToLong(String Value) +110
[InvalidCastException: Conversion from string "inline; filename=\" + myFile + " to type 'Long' is not valid.]
Microsoft.VisualBasic.CompilerServices.Conversions.ToLong(String Value) +428
cmswebasp.CMSModdoclinks.DownloadFile(String file) +1704
cmswebasp.CMSModdoclinks.Page_Load(Object sender, EventArgs e) +625
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
以下是该页面的代码片段:
Response.AddHeader("Content-Disposition", "inline; filename=" & file)
Dim fi As New FileInfo(myFile)
Response.AddHeader("Content-Length", fi.Length)
Dim contentType As String = ""
Dim fileExt As String = file.Split(".")(1)
Select Case fileExt
Case "htm"
contentType = "application/text"
Case Else
contentType = "application/octet-stream"
End Select
Response.ContentType = contentType
Response.WriteFile(myFile)
我是否必须使用htmlwriter对象做某事?我不能让它打开一个显示文件的新浏览器窗口,或者如果以这种方式使用它是否必须提示用户?
答案 0 :(得分:2)
废弃整页(.aspx)方法而不是使用通用处理程序(.ashx)。 .aspx页面将进行大量内置加载以初始化通常在ASP.NET网页中使用的所有状态,而通用处理程序仅初始化最小值以将输出发送回客户端
在使用通用处理程序时,您还需要实现System.Web.SessionState.IRequiresSessionState
来获取会话状态,因为默认情况下它不会加载会话状态。
一个例子:
Public Class FileWrapper
Implements System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
' Validate session...
' Set output content type based on extension of requested file
Dim fileName As String = context.Request.QueryString("file")
Dim fileExt As String = fileName.Split("."c)(1).ToLowerInvariant()
Select Case fileExt
Case "htm", "html"
context.Response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html
Case Else
context.Response.AddHeader("Content-Disposition", "attachment; filename=" & fileName)
context.Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet
End Select
context.Response.WriteFile(fileName)
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
注意:如果在IIS 7上托管,则需要从<httpHandler>
中删除所有<system.web>
个注册,并将其注册为<handler>
中的<system.webServer>
注册。
例如(根据需要更正使用您的命名空间):
<system.webServer>
<!-- For IIS 7 -->
<handlers>
<add name="FileWrapperHandler" path="FileWrapper.ashx" verb="*" type="MyNamespace.FileWrapper"/>
</handlers>
</system.webServer>
另一个注意事项:如果 使用集成管道(IIS 7的默认设置)为IIS 7主机进行开发,那么我建议您使用(并在必要时安装)适用于您的Web的IIS Express选项项目。这将被发现进入您的Web项目的属性,左侧的Web选项卡,然后在Servers部分,选择Use Local IIS Web Server单选按钮,并选中下面的Use IIS Express。
这将使您的开发环境更加与生产环境的行为方式保持同步。
答案 1 :(得分:0)
当您致电Response.WriteFile()
时,服务器可能会丢弃您手动设置的内容类型标头。找出客户端收到它时实际内容类型标头的内容。 Firebug会告诉您是否查看其“网络”标签。
如果是这种情况,请在致电Response.ContentType
后尝试设置Response.WriteFile()
。或者,您可以尝试将文件读入字符串并使用Response.Write()
代替WriteFile
。
答案 2 :(得分:0)
经过一些讨论后,由于用户可能通过Word文档或其他来源中的链接进入网站,看起来最好使用lobotomized Page
而不是通用处理程序。在浏览器之外。
我们发现aspx页面能够在这个实例中恢复会话,而ashx却没有。因此,我正在为aspx解决方案提供代码:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Validate session...
' Set output content type based on extension of requested file
Dim fileName As String = Request.QueryString("file")
Dim fileExt As String = fileName.Split("."c)(1).ToLowerInvariant()
Select Case fileExt
Case "htm", "html"
Response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html
Case Else
Response.ClearHeaders()
Response.AppendHeader("Content-Disposition", "attachment; filename=" & fileName)
Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet
End Select
Response.WriteFile(fileName)
Response.Flush()
Response.Close()
End Sub
无论aspx标记本身放置什么都没关系,因为无论如何都不会渲染。
请注意,由于我们已关闭响应流,因此可能会导致Web主机上的某些日志条目尝试“访问已关闭的流”,但页面将照常继续处理。这是基本上劫持正常页面流量的价格之一。