发送 TMemoryStream 作为邮件附件
Sending TMemoryStream as mail attachment
我正在使用 TfrxPDFExport 将 FastReport 导出为 PDFFile。我创建了一个函数 returns 我将 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 的 TIdMessage
组件在您可以附加到它的数据类型方面非常灵活。
例如,Indy 有一个 TIdAttachmentMemory
class 你可以使用,例如:
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
派生您自己的 class,例如:
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;
或者,你可以写一个class直接发送原来的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;
我正在使用 TfrxPDFExport 将 FastReport 导出为 PDFFile。我创建了一个函数 returns 我将 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 的 TIdMessage
组件在您可以附加到它的数据类型方面非常灵活。
例如,Indy 有一个 TIdAttachmentMemory
class 你可以使用,例如:
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
派生您自己的 class,例如:
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;
或者,你可以写一个class直接发送原来的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;