問題
最近同事詢問一個 Crystal Report 匯出成 PDF 檔案時,在 Browser 中呈現會全都是空白的內容。
透過 Adobe Reader 開啟卻會出現「開啟此文件時出錯。 檔案已損壞且無法修復。」的錯誤。
除錯
程式碼很簡單,就是利用 ReportDocument 將報表檔 Load 進來,並設定資料庫連線及報表參數後,
呼叫 ExportToHttpResponse 匯出 PDF
1 | // ... ReportDocument 將報表檔 Load 進來,並設定資料庫連線及報表參數 ... |
檔案已損壞且無法修復 有可能是檔案內容有可能被更改,所以導致不符合 PDF 的規範。
透過 Notepad++ 開起來比較,正常的 PDF 檔案它的編碼是「ANSI」,
損壞的 PDF 檔案它的編碼卻是「UTF8」。
1.如果調整程式,透過 ExportToDisk 存檔在 Server 上,產出的 PDF 檔案是 OK 的。
2.不透過 ReportDocument ,直接 Response.WriteFile(正常的 PDF 檔),結果 PDF 編碼又變成 UTF8 ,Chrome 來看也都是空空的。
3.在 PostBack 的事件中,Response.WriteFile(正常的 PDF 檔),結果 PDF 編碼是 ANSI ,檔案就正常了。
4.行為 GET ,從 Server 端到 Client 之中,應該有什麼程序在處理, 導致破壞了原本正常的 PDF 內容。
5.這種程序在 IIS 上有可能是 ISAPI 篩選器,ASP.NET 中有可能是 HttpModule or HttpHandler,ASP.NET Core 就是 Middleware
6.檢查 IIS 上並無 ISAPI 篩選器
7.檢查 web.config 中並沒有設定特別的 HttpModule 或是 HttpHandler
8.檢查 global.asax => 結果在 Application_BeginRequest 中,有設定 HttpResponse.Filter
1 | protected void Application_BeginRequest(object sender, EventArgs e) |
那個 ScriptDeferFilter 是將頁面中的 script tag 移到最後,並會以 UTF8 輸出,所以就導致匯出 PDF 發生錯誤
所以調整程式在匯出 Report PDF 那程式程不要使用 Filter 即可。
原來是 Filter 惹的禍,QQ
參考資源
HttpResponse.Filter
How to Export a Crystal Report to a PDF file Programmatically in ASP.NET?
C# System.IO.Path.GetTempFileName 會產生 IOException 檔案存在(The file exists)的錯誤
Fast page loading by moving ASP.NET AJAX scripts after visible content