Отправка TMemoryStream в качестве почтового вложения - PullRequest
0 голосов
/ 29 января 2020

Я экспортирую FastReport как PDFFile, используя TfrxPDFExport. Я сделал функцию, которая возвращает мне 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. Поэтому я думаю, что лучше сохранить TMemoryStream как временный файл, а затем отправить его как вложение. Но как только я выполняю

PDFMemoryStream.SaveToFile('c:\\PDFExp.pdf');

, я получаю нарушение прав доступа. Что я сделал не так? Благодаря.

1 Ответ

2 голосов
/ 29 января 2020

Вам не нужно сохранять TMemoryStream в файл, чтобы прикрепить его к электронному письму. Компонент Indy TIdMessage гибок в типах данных, которые вы можете присоединить к нему.

Например, у 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...