簡體   English   中英

wkhtmltopdf在Perl中使用STDIN和STDOUT與Email :: Mime

[英]wkhtmltopdf using STDIN and STDOUT in Perl with Email::Mime

我正在嘗試從HTML生成即時生成的訂單收據的PDF,然后通過電子郵件將其發送給某人。

我真的不想創建文件,將其附加到電子郵件中,然后刪除該文件,所以我試圖通過STDIN(來自Perl)將html發送到wkhtmltopdf,然后在電子郵件中捕獲wkhtmltopdf的PDF輸出使用 MIME :: Lite 電子郵件:: Mime的附件。

使用Perl 絕對可以使用此功能,使人們可以從我的網站下載動態生成的PDF文件,但是嘗試將其與 MIME :: Lite Email :: Mime一起使用無效。 (它可能會起作用,但是由於它已經過時,我們改用Email :: Mime)

我絕對可以肯定,這是由於我對使用文件句柄,管道,反引號和其他不常使用的東西缺乏基本的了解,所以我想更好地掌握這些東西。

這是有效的方法:

#!/usr/bin/perl
#### takes string containing HTML and outputs PDF to browser to download
#### (otherwise would output to STDOUT)

print "Content-Disposition: attachment; filename='testPDF.pdf'\n";
print "Content-type: application/octet-stream\n\n";

my $htmlToPrint = "<html>a bunch of html</html>";

### open a filehandle and pipe it to wkhtmltopdf
### *the arguments "- -" tell wkhtmltopdf to get 
###  input from STDIN and send output to STDOUT*
open(my $makePDF, "|-", "wkhtmltopdf", "-", "-") || die("$!");
print $makePDF $htmlToPrint;  ## sends my HTML to wkhtmltopdf which streams immediately to STDOUT

exit 1;

您可以從Apache直接運行它,它將向用戶顯示一個下載對話框,並下載一個名為'testPDF.pdf'的可讀,正確的pdf。

編輯:解決方案是Capture :: Tiny模塊(和Email :: Mime ):

#!/usr/bin/perl
use Capture::Tiny qw( capture );
use Email::Sender::Simple;
use Email::MIME::Creator;

my $htmlToPrint = "<html>a bunch of html</html>";

### it's important to capture STDERR as well, since wkhtmltopdf outputs
### its console messages on STDERR instead of STDOUT, so it can output
### the PDF to STDOUT; otherwise it will spam your error log    
(my $pdfstream, my $consoleOutput, my @retvals) = capture {
    open(my $makePDF, "|-", "wkhtmltopdf", "-", "-") || die("$!");
    print $makePDF $htmlToPrint;
};

my @parts = (
Email::MIME->create(
    attributes => {
        content_type => "text/plain",
        disposition  => "inline",
        charset      => "US-ASCII",
        encoding     => "quoted-printable",
    },
    body_str => "Your order receipt is attached as a PDF.",
),
Email::MIME->create(
    attributes => {
        filename     => "YourOrderReceipt.pdf",
        content_type => "application/pdf",
        disposition  => "attachment",
        encoding     => "base64",  ## base64 is ESSENTIAL, binary and quoted-printable do not work!
        name         => "YourOrderReceipt.pdf",
    },
    body => $pdfstream,
),
);

my $email = Email::MIME->create(
  header_str => [
      From => 'Some Person <me@mydomain.com>',
      To   => 'customer@theirdomain.com',
      Subject => "Your order receipt is attached...",
  ],
  parts => [ @parts ],
);

Email::Sender::Simple->send($email);
exit 1;

現在所有這些都可以完美運行。

大部分問題似乎是wkhtmltopdf沒有緩沖PDF輸出並逐行發送; 一旦從STDIN獲得HTML輸入,它將立即將所有PDF輸出流式傳輸到STDOUT。

我認為這就是為什么我無法使open2或open3正常工作的原因。

我也嘗試open (my $pdfOutput, "echo \\"$htmlToPrint\\"| wkhtmltopdf - -|") ,但這在外殼中運行,因此即使$htmlToPrint用引號引起來,命令$htmlToPrint HTML。

希望有人覺得這有幫助...

您需要使用open2或open3將輸入發送到cmd,然后在不使用反引號的情況下收集其輸出。

local(*HIS_IN, *HIS_OUT, *HIS_ERR);
my $pid = open3(*HIS_IN, *HIS_OUT, *HIS_ERR,'wkhtmltopdf', '-', '-');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

您可以使用其他更新穎的方法來發送電子郵件:

  use Email::MIME::Creator;
  use IO::All;

  # multipart message
  my @parts = (
      Email::MIME->create(
          attributes => {
              filename     => "report.pdf",
              content_type => "application/pdf",
              encoding     => "quoted-printable",
              name         => "2004-financials.pdf",
          },
          #body => io( *HIS_OUT )->all, it may work
          body => *HIS_OUT,

      ),
      Email::MIME->create(
          attributes => {
              content_type => "text/plain",
              disposition  => "attachment",
              charset      => "US-ASCII",
          },
          body_str => "Hello there!",
      ),
  );

  my $email = Email::MIME->create(
      header_str => [ From => 'casey@geeknest.com' ],
      parts      => [ @parts ],
  );
  # standard modifications
  $email->header_str_set( To            => rcpts()        );

  use Email::Sender::Simple;
  Email::Sender::Simple->send($email);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM