如果你的檔案下載程式,使用者反映每個文字檔的尾巴都會被塞一句「Error」,你會怎麼想?
「這一定是被駭客攻擊了...」
是的,我很想就這麼告訴使用者,但...我真的好心虛,於是,老老實實打開程式碼好好檢查一番。
Partial Class MainPage_FileDownloadSeal Inherits CommonPage Private Sub MainPage_FileDownloadSeal_Load(sender As Object, e As EventArgs) Handles Me.Load Dim wsfile As New AttachFileinfo() Try Dim FileID As String = Request("File").ToString().Trim() Dim ds_file As DataSet = wsfile.getFileBase(FileID) Dim strFilePath As String = ds_file.Tables(0).Rows(0)("檔案存放路徑").ToString() + ds_file.Tables(0).Rows(0)("系統檔名").ToString() Dim strFileName As String = ds_file.Tables(0).Rows(0)("使用者上傳檔名").ToString() If strFilePath.Length <> 0 Then If File.Exists(strFilePath) Then If strFilePath.Length > 0 Then Dim strSubName As String strSubName = strFilePath.Substring(strFilePath.LastIndexOf(".") + 1, strFilePath.Length - strFilePath.LastIndexOf(".") - 1) '"檔案分類" Select Case strSubName.ToUpper() Case "TXT" Response.ContentType = "text/html" Exit Select Case "HTM" Response.ContentType = "text/html" Exit Select Case "HTML" Response.ContentType = "text/html" Exit Select Case "DOCX", "DOC" Response.ContentType = "application/msword" Exit Select Case "XLS" Response.ContentType = "application/vnd.ms-excel" Exit Select Case "GIF" Response.ContentType = "image/gif" Exit Select Case "JPG" Response.ContentType = "image/JPG" Exit Select Case "BMP" Response.ContentType = "image/bmp" Exit Select Case "SWF" Response.ContentType = "application/x-shockwave-flash" Exit Select Case "PDF" Response.ContentType = "application/pdf" Exit Select Case Else 'specify that the response is a stream that cannot be read by the 'client and must be downloaded Response.ContentType = "application/octet-stream" Exit Select End Select Response.Clear() '決定檔案存檔預設名稱 Response.AddHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(strFileName)) Response.WriteFile(strFilePath) Response.[End]() End If End If End If Catch ex As Exception Response.Write("Error") End Try End Sub End Class
這應該再普通不過了吧,別人有的我也有,別人沒加的,我還老實的都有加。你看看,那個 Try ... Catch ,就是我特別力求完整而補上的。
但重點是,別人沒錯,我錯了啊!?
在參考了「小筆記-避免 ThreadAbortException 的Response.End() 替代寫法」,其中一段說著:
Response.End() 會觸發 ThreadAbortException 造成中斷。若 Response.End() 被 try catch包覆,則會進入 catch 流程。
所以我的程式:
Try Response.Clear() '決定檔案存檔預設名稱 Response.AddHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(strFileName)) Response.WriteFile(strFilePath) Response.[End]() Catch ex As Exception Response.Write("Error") End Try
剛好把 Response.End() 放在 Try 裡頭,當他執行到 Response.End() 時,還沒來的及結束,就先去執行了 Catch 裡面的 Response.Writer("Error")
這也就解釋了,為何我的使用者所下載的檔案尾巴,都會留下一句:Error
所以,正確寫法應該是:
Try Response.Clear() '決定檔案存檔預設名稱 Response.AddHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(strFileName)) Response.WriteFile(strFilePath) Catch ex As Exception Response.Write("Error") Finally Response.[End]() End Try
把 Response.End() 放到 Finally 裡面