[英]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.