我正在尝试从也即时生成的 HTML 即时生成订单收据的 PDF,然后通过电子邮件将其发送给某人。
我真的不想创建文件,将其附加到电子邮件,然后删除文件,所以我试图通过 STDIN(来自 Perl)将 html 发送到 wkhtmltopdf,然后在电子邮件中捕获来自 wkhtmltopdf 的 PDF 输出附件使用MIME::Lite Email::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 - -|")
,但这在 shell 中运行,所以即使用$htmlToPrint
引号括起来,命令也会阻塞 HTML 中使用的符号。
希望有人觉得这有帮助...