Delphi Indy 10 pdf 附件无法读取

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

我正在尝试将报告导出为 PDF,然后将其附加到电子邮件和/或彩信中。我将 TFileStream 编码为 TStringStream,然后将其附加到电子邮件,但是 cannot open it. 使用相同的 TStringStream,我将其附加到彩信,它按预期工作。 Indy 方法似乎适用于流,我做错了什么?

编辑:电子邮件附件和电子邮件正文显示在附加文件中,这就是它不可读的原因。如果我对附件的内容进行 Base64 解码,它就可以工作。

有什么想法为什么会发生这种情况吗?

Email Attachment
MMS Attachment

ReportPdf := TStringStream.Create;
try
  if (CreateReportPdf(QuickRep1, ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', IsReprint)) then
  begin
    if (Assigned(ReportPdf)) then
    begin
      SendReceiptEmail(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test', QryInfoReplyToEmailAddress.AsString);
      SendReceiptSMS(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test');
    end;
  end;
finally
  ReportPdf.Free;
end;

这里是导出报告的位置。这按预期工作。

function CreateReportPdf(QuickRep: TQuickRep; var ReportPdf: TStringStream; const PrintNumber, ReportName: string; const IsReprint: Boolean): Boolean;
var
  aPdf: TQRPDFDocumentFilter;
  tmpPath, tmpFileName: string;
  fs: TFileStream;
begin
  Result := False;
  if (not Assigned(QuickRep)) then
    Exit;

  tmpPath := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + '\Temp\';
  tmpFileName := CreateTmpFileName(tmpPath, Format('%s_%s', [ReportName, PrintNumber]), '.pdf');

  aPdf := TQRPDFDocumentFilter.Create(tmpPath + tmpFileName);
  fs := nil;

  try
    try
      aPdf.CompressionOn := True;
      aPdf.PageLength := 11;
      QuickRep.ExportToFilter(aPdf);

      fs := TFileStream.Create(tmpPath + tmpFileName, fmOpenRead);
      fs.Position := 0;
      TNetEncoding.Base64.Encode(fs, ReportPdf);

      Result := True;
    except
      ShowMessage('Failed to create report PDF.');
      Result := False;
    end;
  finally
    aPdf.Free;
    fs.Free;
  end;
end;

我尝试解码 Base64(见下文)——没有帮助。

procedure SendReportEmail(ReportPdf: TStringStream; const PrintNumber, ReportName, Recipients, MessageText, ReplyTo: string);
var
  Attachment: TStringList;
  Host: string;
  Port: Integer;
  // ReportPdfDecoded: TStringStream;
  I: Integer;
begin
  if (ReportPdf.DataString.Length > 0) then
  begin
    ReportPdf.Position := 0;   
    // ReportPdfDecoded := TStringStream.Create;
    Attachment := TStringList.Create();

    try
      // TNetEncoding.Base64.Decode(ReportPdf, ReportPdfDecoded);
      // Attachment.AddObject('stream/pdf', ReportPdfDecoded);
      Attachment.AddObject('stream/pdf', ReportPdf);          

      Host := GetConfigValue(cCFG_EMAIL_HOST).AsString;
      Port := GetConfigValue(cCFG_EMAIL_PORT).AsInteger;
      From := GetConfigValue(cCFG_EMAIL_FROM).AsString;

      Lib.SendEmail(Host, From, Recipients, ReportName + '_' + PrintNumber,
        MessageText, '', '', ReplyTo, Port, False, Attachment);
    finally
      for I := Attachment.Count -1 downto 0 do
        Attachment.Objects[I].Free;
      Attachment.Free;
      // ReportPdfDecoded.Free;
    end;
  end;
end;

我在这里遗漏了一些明显的东西吗?感谢您的关注。

procedure SendEmail(Host, From, Recipients, Subject, Body, CC, BCC, ReplyTo: string; Port: Integer; IsBodyHtml: Boolean; Attachments: TStrings);
var
  IdSMTP: TIdSMTP;
  IdMessage: TIdMessage;
  builder: TIdCustomMessageBuilder;
  s: Integer;
begin
  IdSMTP := TIdSMTP.Create(nil);
  IdMessage := TIdMessage.Create(nil);

  try
    if IsBodyHtml then
    begin
      builder := TIdMessageBuilderHtml.Create;
      TIdMessageBuilderHtml(builder).Html.Text := Body
    end
    else
    begin
      builder := TIdMessageBuilderPlain.Create;
    end;

    try
      if (Assigned(Attachments)) then
      begin
        IdMessage.ContentType := 'multipart/mixed';
        for s := 0 to Attachments.Count -1 do
        begin
          if (Attachments.Strings[s] = 'stream/pdf') then
          begin
            builder.PlainTextCharSet := 'utf-8';
            builder.Attachments.Add(TStringStream(attachments.Objects[s]), 'application/pdf');
          end
          else
            builder.Attachments.Add(attachments.ValueFromIndex[s]);
        end;
      end;

      builder.FillMessage(IdMessage);
    finally
      builder.Free;
    end;

    IdMessage.From.Address := From;
    IdMessage.Recipients.EMailAddresses := Recipients;
    IdMessage.Subject := Subject;
    IdMessage.Body.Text := Body;
    IdMessage.CCList.EMailAddresses := CC;
    IdMessage.BccList.EMailAddresses := BCC;
    IdMessage.ReplyTo.EMailAddresses := ReplyTo;

    if not IsBodyHtml then
      IdMessage.Body.Text := Body;
      
    try
      IdSMTP.Host := Host;
      IdSMTP.Port := Port;

      IdSMTP.Connect;
      IdSMTP.Send(IdMessage);
      IdSMTP.Disconnect;
    finally
      IdSMTP.Free;
    end;
  finally
    IdMessage.Free;
  end;
end;
email delphi indy10
1个回答
1
投票

在使用 Indy 通过电子邮件发送 PDF 之前,无需手动对 PDF 进行 Base64 编码(如果您需要 Base64 进行 SMS,则应在发送 SMS 时单独处理)。 Indy 的

TIdMessage
组件可以为您处理 base64,因此只需按原样附加原始 PDF 并将其
ContentTransfer
属性设置为
'base64'
。由于您要将 PDF 存储到
TStream
中,然后将其附加到电子邮件中,因此您应该仅存储 PDF 的原始字节(即使用
TMemoryStream
TFileStream
),不要存储预编码版本PDF 的。

尝试更多类似这样的事情:

ReportPdf := TMemoryStream.Create;
try
  if CreateReportPdf(QuickRep1, ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', IsReprint) then
  begin
    SendReceiptEmail(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test', QryInfoReplyToEmailAddress.AsString);
    ...
  end;
finally
  ReportPdf.Free;
end;
function CreateReportPdf(QuickRep: TQuickRep; ReportPdf: TMemoryStream; const PrintNumber, ReportName: string; const IsReprint: Boolean): Boolean;
var
  aPdf: TQRPDFDocumentFilter;
  tmpPath, tmpFileName: string;
begin
  Result := False;
  if not Assigned(QuickRep) then
    Exit;
    
  tmpPath := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + '\Temp\';
  tmpFileName := CreateTmpFileName(tmpPath, Format('%s_%s', [ReportName, PrintNumber]), '.pdf');
    
  try
    aPdf := TQRPDFDocumentFilter.Create(tmpPath + tmpFileName);    
    try
      aPdf.CompressionOn := True;
      aPdf.PageLength := 11;
      QuickRep.ExportToFilter(aPdf);
    
      ReportPdf.LoadFromFile(tmpPath + tmpFileName);
      Result := True;
    finally
      aPdf.Free;
    end;
  except
    ShowMessage('Failed to create report PDF.');
  end;
end;
procedure SendReportEmail(ReportPdf: TMemoryStream; const PrintNumber, ReportName, Recipients, MessageText, ReplyTo: string);
var
  Attachment: TStringList;
  Host, From: string;
  Port: Integer;
begin
  if ReportPdf.Size > 0 then
  begin
    ReportPdf.Position := 0;   

    Attachment := TStringList.Create;    
    try
      Attachment.AddObject('stream/pdf', ReportPdf);          
    
      Host := GetConfigValue(cCFG_EMAIL_HOST).AsString;
      Port := GetConfigValue(cCFG_EMAIL_PORT).AsInteger;
      From := GetConfigValue(cCFG_EMAIL_FROM).AsString;
    
      Lib.SendEmail(Host, From, Recipients, ReportName + '_' + PrintNumber,
        MessageText, '', '', ReplyTo, Port, False, Attachment);
    finally
      Attachment.Free;
    end;
  end;
end;
procedure SendEmail(Host, From, Recipients, Subject, Body, CC, BCC, ReplyTo: string; Port: Integer; IsBodyHtml: Boolean; Attachments: TStrings);
var
  IdSMTP: TIdSMTP;
  IdMessage: TIdMessage;
  builder: TIdMessageBuilderHtml;
  attach: TIdMessageBuilderAttachment;
  I: Integer;
begin
  IdMessage := TIdMessage.Create(nil);  
  try
    builder := TIdMessageBuilderHtml.Create;
    try
      builder.PlainTextCharSet := 'utf-8';
      builder.HtmlCharSet := 'utf-8';

      if IsBodyHtml then
        builder.Html.Text := Body
      else
        builder.PlainText.Text := Body;
    
      if Assigned(Attachments) then
      begin
        for I := 0 to Attachments.Count - 1 do
        begin
          if Attachments.Strings[I] = 'stream/pdf' then
          begin
            attach := builder.Attachments.Add(TMemoryStream(attachments.Objects[I]), 'application/pdf');
            attach.ContentTransfer := 'base64';
          else
            attach := builder.Attachments.Add(attachments.ValueFromIndex[I]);

          // optional: set attach.WantedFileName or attach.FileName if desired...
        end;
      end;
    
      builder.FillMessage(IdMessage);
    finally
      builder.Free;
    end;
    
    IdMessage.From.Address := From;
    IdMessage.Recipients.EMailAddresses := Recipients;
    IdMessage.Subject := Subject;
    IdMessage.CCList.EMailAddresses := CC;
    IdMessage.BccList.EMailAddresses := BCC;
    IdMessage.ReplyTo.EMailAddresses := ReplyTo;

    IdSMTP := TIdSMTP.Create(nil);
    try
      IdSMTP.Host := Host;
      IdSMTP.Port := Port;
    
      IdSMTP.Connect;
      try
        IdSMTP.Send(IdMessage);
      finally
        IdSMTP.Disconnect;
      end;
    finally
      IdSMTP.Free;
    end;
  finally
    IdMessage.Free;
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.