将TMemoryStream作为邮件附件发送

问题描述 投票:0回答:1

我正在使用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');

我遇到访问冲突。我做错了什么?谢谢。

delphi stream email-attachments indy delphi-10-seattle
1个回答
1
投票

您无需将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;
© www.soinside.com 2019 - 2024. All rights reserved.