我正在尝试编写一个PHP脚本,该脚本使用pdftk应用程序将XFDF与PDF表单合并,并将合并的PDF输出给用户。根据pdftk文档,我可以通过stdin
传递表单数据,并将PDF输出到stdout
流。从命令行使用pdftk的常规文件非流方式是:
pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf
要在命令行上使用流,请输入:
pdftk blankform.pdf fill_form - output -
我有几个问题:
1)我已经使用xfdf文件(而不是stdout
)通过stdin
获得pdftk返回输出,如下所示:
exec("pdftk blankform.pdf fill_form formdata.xfdf output -", $pdf_output);
file_put_contents("filledform.pdf",$pdf_output);
但它创建的pdf已损坏,根据Adobe Reader,用文本编辑器快速查看文件显示,至少,它不是将行结束设置在应有的位置。我有一个相同的PDF由pdftk创建,它输出到一个文件,pdf在文本编辑器中看起来很好,所以我知道它不是pdftk输出坏数据。
2)我不能为我的生活弄清楚如何在PHP中设置stdin
流,以便我可以将该流用作我对pdftk的输入。从我在PHP文档中读到的内容来看,stdin
是只读的,那么如何进入该流?
理想情况下,我希望保持这一点非常简单并避免使用proc_open()
。我尝试使用该功能并且不是非常成功,这可能是我的错,而不是功能,但实际上我的目标很简单,我宁愿避免使用我不需要的强大功能。
理想情况下,我的代码看起来像:
$form_data_raw = $_POST;
$form_data_xfdf = raw2xfdf($form_data_raw); //some function that turns HTML-form data to XFDF
$blank_pdf_form = "blankform.pdf";
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="output.pdf"');
passthru("pdftk $blank_pdf_form fill_form $form_data_xfdf output -);
只是抬头,可以将实际的xml字符串放在命令行中,但是我的结果是非常不可靠。
在很多帮助下,我现在明白我的真正问题是“如何在PHP中将变量传递给命令行”。显然,proc_open是最好的方式,或者至少是最直接的方式。因为我花了很长时间才弄清楚,因为我对谷歌的研究表明其他人可能会苦苦挣扎,我会发布专门针对我的问题的代码:
$blank_pdf_form = "blankform.pdf";
$cmd = "pdftk $blank_pdf_form fill_form - output -";
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
//row2xfdf is made-up function that turns HTML-form data to XFDF
fwrite($pipes[0], raw2xfdf($_POST));
fclose($pipes[0]);
$pdf_content = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="output.pdf"');
echo $pdf_content;
}
答案 0 :(得分:26)
我不确定你想要达到的目标。您可以使用URL php:// stdin读取stdin。但这是来自PHP命令行的stdin,而不是来自pdftk(通过exec)的stdin。
但我会给proc_open()
<?php
$cmd = sprintf('pdftk %s fill_form %s output -','blank_form.pdf', raw2xfdf($_POST));
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => null,
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
fwrite($pipes[0], stream_get_contents(STDIN)); // file_get_contents('php://stdin')
fclose($pipes[0]);
$pdf_content = stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="output.pdf"');
echo $pdf_content;
}
?>
答案 1 :(得分:-1)
1)为什么要输出标准输出然后将这些东西放入文件中?为什么不将pdftk转储到文件中,即
exec("pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf");
2)使用proc_open()
。随意发布您对该功能的任何问题。