問題描述
我正在嘗試編寫一個(gè) PHP 腳本,該腳本使用 pdftk 應(yīng)用程序?qū)?XFDF 與PDF 格式并將合并后的 PDF 輸出給用戶.根據(jù) pdftk 文檔,我可以通過 stdin
傳遞表單數(shù)據(jù),并將 PDF 輸出到 stdout
流.從命令行使用 pdftk 的正常文件而非流方式是:
I am trying to write a PHP script that uses the pdftk app to merge an XFDF with a PDF form and output the merged PDF to the user. According to the pdftk documentation, I can pass the form data in via stdin
and have the PDF output to the stdout
stream. The normal, file-not-stream way to use pdftk from the command line is:
pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf
要在命令行上使用流,您需要輸入:
to use streams on the command line, you'd enter:
pdftk blankform.pdf fill_form - output -
我有幾個(gè)問題:
1) 我已經(jīng)讓 pdftk 使用 xfdf 文件(而不是 stdin
)通過 stdout
返回輸出,如下所示:
1) I have gotten pdftk to return output via stdout
using an xfdf file (instead of stdin
) like so:
exec("pdftk blankform.pdf fill_form formdata.xfdf output -", $pdf_output);
file_put_contents("filledform.pdf",$pdf_output);
但根據(jù) Adob??e Reader 的說法,它創(chuàng)建的 pdf 已損壞,并且使用文本編輯器快速瀏覽該文件表明,至少,它沒有將行尾設(shè)置在應(yīng)有的位置.我有一個(gè)由 pdftk 創(chuàng)建的完全相同的 PDF,它輸出到一個(gè)文件,并且 pdf 在文本編輯器中看起來不錯(cuò),所以我知道它不是 pdftk 輸出錯(cuò)誤數(shù)據(jù).
But the pdf that it creates is corrupt, according to Adobe Reader and a quick peek at the file with a text editor shows that, at the very least, it is not setting the line endings where they should be. I have an identical PDF created by pdftk where it output to a file, and the pdf looks fine in the text editor, so I know that it's not pdftk that's outputting bad data.
2) 我一生都無法弄清楚如何在 PHP 中設(shè)置 stdin
流,以便我可以使用該流作為 pdftk 的輸入.從我在 PHP 文檔中讀到的內(nèi)容來看,stdin
是只讀的,那么任何東西如何進(jìn)入該流?
2) I can not for the life of me figure out how to set the stdin
stream in PHP so that I can use that stream as my input for pdftk. From what I'm reading on the PHP documentation, stdin
is read-only, so how does anything ever get into that stream?
理想情況下,我想保持這個(gè)非常簡單并避免使用 proc_open()
.我嘗試使用該函數(shù)但不是很成功,這可能是我的錯(cuò),而不是函數(shù)的錯(cuò),但實(shí)際上我的目標(biāo)很簡單,我寧愿避免使用我不需要的強(qiáng)大函數(shù).
Ideally, I would like to keep this really simple and avoid using proc_open()
. I attempted to use that function and wasn't very sucessful, which is probably my fault, not the function's, but really my goals are simple enough I'd rather avoid using robust functions I don't need.
理想情況下,我的代碼如下所示:
Ideally my code would look something like:
$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 -);
請(qǐng)注意,可以將實(shí)際的 xml 字符串放在命令行中,但是我得到了非常不可靠的結(jié)果.
Just a heads up, it is possible to put the actual xml string in the command line, but I've had very unreliable results with this.
在很多幫助下,我現(xiàn)在明白我真正的問題是如何通過管道將變量傳遞到 PHP 中的命令行執(zhí)行".顯然 proc_open 是最好的方法,或者至少是最直接的方法.由于我花了很長時(shí)間才弄明白這一點(diǎn),而且我對(duì)谷歌的研究表明其他人可能正在苦苦掙扎,我將發(fā)布專門解決我的問題的代碼:
With much help, I now understand that my real question was "how can pipe a variable to a command line execution in PHP". Apparently proc_open is the best way to go, or at least the most straightforward. Since it took me forever to figure this out and since my research on Google suggests others may be struggling, I'll post the code that specifically worked for my problem:
$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;
}
推薦答案
我不確定您要實(shí)現(xiàn)的目標(biāo).您可以使用 URL php://stdin 讀取標(biāo)準(zhǔn)輸入.但這是來自 PHP 命令行的標(biāo)準(zhǔn)輸入,而不是來自 pdftk(通過 exec)的標(biāo)準(zhǔn)輸入.
I'm not sure about what you're trying to achieve. You can read stdin with the URL php://stdin. But that's the stdin from the PHP command line, not the one from pdftk (through exec).
但我會(huì)給 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;
}
?>
這篇關(guān)于如何將變量作為標(biāo)準(zhǔn)輸入從 PHP 傳遞到命令行的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!