我正在使用TfrxPDFExport将FastReport导出为PDFFile。我做了一个函数,可以将PDF返回为IStream:
Function TPDFReport.GetAsFile (): IStream;
var
MStream: TMemoryStream;
Begin
MStream := TMemoryStream.Create;
try
With formReport.Create (NIL) do begin
frxPDFExport.Stream := MStream;
frxReport.PrepareReport;
frxReport.Export(frxPDFExport);
end;
Result := TStreamAdapter.Create(MStream) as IStream;
finally
end;
End;
然后在另一个单元中执行此功能,获取IStream并将其加载到TMemoryStream中:
PDFOleStream := TOleStream.Create(PDFReport.GetAsFile ());
PDFMemoryStream.LoadFromStream(PDFOleStream);
现在我有了MemoryStream,但是我真的不知道下一步。我在网上搜索了一下,发现无法与Indy一起将Stream作为邮件附件发送。因此,我认为最好将TMemoryStream保存为临时文件,然后将其作为附件发送。但是,一旦我执行
PDFMemoryStream.SaveToFile('c:\\PDFExp.pdf');
我遇到访问冲突。我做错了什么?谢谢。
您无需将TMemoryStream
保存到文件中,只需将其附加到电子邮件即可。 Indy有一个您可以使用的TIdAttachmentMemory
类,例如:
uses
..., IdAttachmentMemory;
var
Attach: TIdAttachmentMemory;
begin
Attach := TIdAttachmentMemory.Create(IdMessage1, PDFMemoryStream); // alternatively, use PDFOleStream instead...
Attach.FileName := 'report.pdf';
// set other properties as needed...
// send the email...
end;
请注意,TIdAttachmentMemory
使用其自己的内部TMemoryStream
,并将源TStream
的数据复制到该内部流中。如果要避免该副本并按原样发送自己的TStream
,则可以从TIdAttachment
派生自己的类,例如:
uses
Classes, IdAttachment, IdMessageParts, IdGlobal;
type
TIdAttachmentStream = class(TIdAttachment)
protected
FDataStream: TStream;
FDataStreamBeforeLoadPosition: TIdStreamSize;
public
constructor Create(Collection: TIdMessageParts; Stream: TStream); reintroduce;
property DataStream: TStream read FDataStream;
function OpenLoadStream: TStream; override;
procedure CloseLoadStream; override;
procedure FinishTempStream; override;
function PrepareTempStream: TStream; override;
end;
constructor TIdAttachmentStream.Create(Collection: TIdMessageParts; Stream: TStream);
begin
inherited Create(Collection);
FDataStream := Stream;
end;
procedure TIdAttachmentStream.CloseLoadStream;
begin
DataStream.Position := FDataStreamBeforeLoadPosition;
end;
function TIdAttachmentStream.OpenLoadStream: TStream;
begin
FDataStreamBeforeLoadPosition := DataStream.Position;
DataStream.Position := 0;
Result := DataStream;
end;
procedure TIdAttachmentStream.FinishTempStream;
begin
DataStream.Position := 0;
end;
function TIdAttachmentStream.PrepareTempStream: TStream;
begin
DataStream.Size := 0;
Result := DataStream;
end;
var
Attach: TIdAttachmentStream;
begin
...
Attach := TIdAttachmentStream.Create(IdMessage1, PDFMemoryStream); // alternatively, use PDFOleStream instead...
Attach.FileName := 'report.pdf';
// set other properties as needed...
// send the email...
...
end;
或者,您可以编写一个类来直接发送原始的IStream
,例如:
uses
Classes, IdAttachment, IdMessageParts, IdGlobal;
type
TIdAttachmentIStream = class(TIdAttachment)
protected
FDataStream: TStream;
FDataStreamBeforeLoadPosition: TIdStreamSize;
public
constructor Create(Collection: TIdMessageParts; Stream: IStream); reintroduce;
destructor Destroy; override;
property DataStream: TStream read FDataStream;
function OpenLoadStream: TStream; override;
procedure CloseLoadStream; override;
procedure FinishTempStream; override;
function PrepareTempStream: TStream; override;
end;
constructor TIdAttachmentIStream.Create(Collection: TIdMessageParts; Stream: IStream);
begin
inherited Create(Collection);
FDataStream := TOleStream.Create(Stream);
end;
destructor TIdAttachmentIStream.Destroy;
begin
FDataStream.Free;
inherited;
end;
procedure TIdAttachmentIStream.CloseLoadStream;
begin
DataStream.Position := FDataStreamBeforeLoadPosition;
end;
function TIdAttachmentIStream.OpenLoadStream: TStream;
begin
FDataStreamBeforeLoadPosition := DataStream.Position;
DataStream.Position := 0;
Result := DataStream;
end;
procedure TIdAttachmentIStream.FinishTempStream;
begin
DataStream.Position := 0;
end;
function TIdAttachmentIStream.PrepareTempStream: TStream;
begin
DataStream.Size := 0;
Result := DataStream;
end;
var
Attach: TIdAttachmentIStream;
begin
...
Attach := TIdAttachmentIStream.Create(IdMessage1, PDFReport.GetAsFile());
Attach.FileName := 'report.pdf';
// set other properties as needed...
// send the email...
...
end;