承接上篇,Web 環境下為避免磁盤權限與安全問題,需將 FastReport 2.5 生成的報表直接導出到記憶體流(TMemoryStream)。本文詳細說明修改 FR_Class 與 TfrHTML2Export 源碼以支援 ExportToStream 並內嵌 CSS 的完整步驟。
在 FR_Class.pas 的 TfrReport 類別中加入:
// 添加導出到記憶體流支援 -- Conch 2007-09-10
procedure TfrReport.ExportToStream(Filter: TfrExportFilter; Stream: TMemoryStream);
var
S: String;
Flag, NeedConnect: Boolean;
begin
DocMode := dmPrinting;
FCurrentFilter := Filter;
if (Preview <> nil) and (EMFPages.Count = 0) then
begin
Preview.Disconnect;
NeedConnect := True;
end
else
NeedConnect := False;
Flag := True;
if Assigned(FCurrentFilter.OnBeforeExport) then
FCurrentFilter.OnBeforeExport(FCurrentFilter.FileName, Flag);
FCurrentFilter.Stream := Stream; { 關鍵:指定輸出流 }
CurReport := Self;
MasterReport := Self;
SavedAllPages := EMFPages.Count;
FCurrentFilter.OnBeginDoc;
ExportBeforeModal(Self);
if Assigned(FCurrentFilter.OnAfterExport) then
FCurrentFilter.OnAfterExport(FCurrentFilter.FileName);
if NeedConnect then
Preview.Connect(Self);
FCurrentFilter := nil;
end;
原版將 CSS 另存為 .css 檔案,導致記憶體流中的 HTML 缺少樣式。找到 SaveStringToFile(ImageFolderFull + CSSFile, S)(FR 2.5 約第 461 行),改為:
if FileName <> '' then
SaveStringToFile(ImageFolderFull + CSSFile, S)
else begin
S := '' + LF;
Stream.Write(S[1], Length(S)); { 直接寫入記憶體流 }
end;
procedure TfrHTML2Export.OnEndDoc;
var
S: string; I, J: Integer; Page: THPage; LastBottom: Integer;
CSSFile, CSSFilePrint, NavFile: string;
H1, H2: string; MaxWidth, MinLeftMargin: Integer;
begin
if Navigator = nil then Exit;
if FPages.Count = 0 then Exit;
{ ... 樣式構建代碼省略 ... }
{ 關鍵修改:CSS 內嵌到流 }
if FileName <> '' then
SaveStringToFile(ImageFolderFull + CSSFile, S)
else begin
S := '' + LF;
Stream.Write(S[1], Length(S));
end;
{ ... 後續分頁/導航器輸出代碼 ... }
{ 注意:所有原本寫檔案的 SaveStringToFile 均需改為 Stream.Write }
end;
var
Rpt: TfrReport;
Ex: TfrHTML2Export;
St: TMemoryStream;
begin
Rpt := TfrReport.Create(nil);
Ex := TfrHTML2Export.Create(nil);
St := TMemoryStream.Create;
try
Rpt.LoadFromFile('Report.frf');
Rpt.PrepareReport;
Ex.Navigator.Align := haLeft;
Ex.ShowDialog := False;
Rpt.ExportToStream(Ex, St); { 導出到記憶體流 }
St.Position := 0;
{ 將 St 內容發送給 HTTP 客戶端 }
finally
Ex.Free; St.Free; Rpt.Free;
end;
end;
| 指標 | 檔案導出 | 記憶體流導出 |
|---|---|---|
| 磁盤 I/O | 有 | 無 |
| 權限問題 | 需寫入權限 | 無 |
| 殘留檔案清理 | 需定時清理 | 自動隨流釋放 |
| 併發衝突 | 檔案名衝突 | 各請求獨立流 |
| 延遲 | 較高 | 極低 |
通過修改 FastReport 源碼新增 ExportToStream 並內嵌 CSS,即可在 Web 服務器組件中高效、安全地生成交叉報表 HTML,無需臨時檔案,完美解決權限與併發問題。