通过ASP.Net中的Response.Writefile在浏览器中显示htm内容

时间:2012-04-18 20:18:15

标签: asp.net vb.net

我正在开发一个我用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对象做某事?我不能让它打开一个显示文件的新浏览器窗口,或者如果以这种方式使用它是否必须提示用户?

3 个答案:

答案 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。

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主机上的某些日志条目尝试“访问已关闭的流”,但页面将照常继续处理。这是基本上劫持正常页面流量的价格之一。