2012-04-18 61 views
1

我工作的一個網站,我繼承了一個與ASP.Net修建,這我只是稍微熟悉。其中一個頁面允許鏈接到文檔(單詞或pdf),當點擊該文檔時,提示用戶保存或打開文件,但不顯示文件的真實路徑。通過這種方式,它可以防止用戶將url粘貼到文件 - 該鏈接指向檢查有效會話的aspx文件,然後檢索文件。HTM內容在ASP.Net

無論如何,因爲有很多遺留代碼,我還需要使用一堆靜態htm文件來做到這一點,但是需要顯示這些文件而不是提示用戶保存它們,這就是現在發生的情況。我嘗試將內容類型更改爲應用程序/文本,應用程序/ html,text/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對象或東西?我不能只是打開一個新的瀏覽器窗口並顯示文件,或者是否必須提示用戶使用這種方式?

回答

2

廢料代替使用通用處理器(ashx的)的整頁(的.aspx)的方法。一個.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中,您將需要從<system.web>刪除任何<httpHandler>登記,而是將它們註冊爲<system.webServer><handler>註冊。

如(正確的,因爲需要使用您的命名空間):

<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部分中選擇使用本地IIS Web服務器單選按鈕,然後選中下面的使用IIS Express。

Use IIS Express

這將使你的開發環境更同步與生產環境將如何表現。

+1

對不起,終於實現了這一點,它的工作原理就像一個魅力 - 我使用http://www.dotnetperls.com/ashx的代碼爲了提供正確的文件名到處理程序。 – 2012-05-04 19:28:24

+0

但是,我唯一的問題是,即使我正在執行IRequiresSessionState,如上所示,我可以訪問URL並因此無需登錄即可訪問該文件...任何想法爲什麼可能是這樣? – 2012-05-04 19:30:09

+0

沒關係,我想我只需要編寫條件代碼,如果他們的會話變量沒有設置,就會阻止用戶訪問頁面。 – 2012-05-04 19:55:06

0

,當你調用Response.WriteFile()的服務器可能會被拋出你手動設置Content-Type頭。找出當客戶端收到它時實際的內容類型標題。 Firebug會告訴你,如果你看看它的淨選項卡。

如果是這樣的情況下,嘗試調用Response.WriteFile()後設置Response.ContentType。或者,您可以嘗試將文件讀入字符串,並使用Response.Write()而不是WriteFile

0

經過一番討論後,似乎您最好使用lobotomized Page,而不是通用處理程序,因爲用戶可能通過Word文檔或瀏覽器之外的其他來源的鏈接訪問網站。

我們發現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主機上的某些日誌條目試圖「訪問封閉的流」,因爲我們已經關閉了響應流,但該頁面將像往常一樣繼續處理。這是支付基本劫持正常頁面流量的價格之一。

+0

我得到了這個工作,以便它將html內聯與其他文件作爲附件提供。但是,我以前遇到的行爲(會話粘性),我今天沒有看到。希望我不只是想象它!在這一點上看起來不太可能,但如果有一些解決方法,我很想知道! – 2012-05-10 16:58:44