如何将变量作为标准输入从 PHP 传递到命令行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2390604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:17:13  来源:igfitidea点击:

How to pass variables as stdin into command line from PHP

phpcommand-linestreamstdinpdftk

提问by Anthony

I am trying to write a PHP script that uses the pdftkapp 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 stdinand have the PDF output to the stdoutstream. The normal, file-not-stream way to use pdftk from the command line is:

我正在尝试编写一个 PHP 脚本,该脚本使用pdftk应用程序将 XFDF 与 PDF 表单合并并将合并的 PDF 输出给用户。根据 pdftk 文档,我可以通过 via 传递表单数据stdin并将 PDF 输出到stdout流。从命令行使用 pdftk 的正常文件非流方式是:

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 -

I have a couple of problems:

我有几个问题:

1) I have gotten pdftk to return output via stdoutusing an xfdf file (instead of stdin) like so:

1)我已经让 pdftk 通过stdout使用 xfdf 文件(而不是stdin)来返回输出,如下所示:

    exec("pdftk blankform.pdf fill_form formdata.xfdf output -", $pdf_output);
    file_put_contents("filledform.pdf",$pdf_output);

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.

但是,根据 Adob​​e Reader 的说法,它创建的 pdf 已损坏,并且使用文本编辑器快速浏览该文件表明,至少,它没有将行尾设置在应有的位置。我有一个由 pdftk 创建的相同 PDF,它输出到一个文件,并且 pdf 在文本编辑器中看起来很好,所以我知道它不是 pdftk 输出错误数据。

2) I can not for the life of me figure out how to set the stdinstream in PHP so that I can use that stream as my input for pdftk. From what I'm reading on the PHP documentation, stdinis read-only, so how does anything ever get into that stream?

2)我一生都无法弄清楚如何stdin在 PHP 中设置流,以便我可以使用该流作为 pdftk 的输入。从我在 PHP 文档stdin中读到的内容来看,它是只读的,那么任何内容如何进入该流?

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.

理想情况下,我想保持这个非常简单并避免使用proc_open(). 我尝试使用该函数但不是很成功,这可能是我的错,而不是函数的错,但实际上我的目标很简单,我宁愿避免使用我不需要的强大函数。

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 -);

Just a heads up, it is possible to put the actual xml string in the command line, but I've had veryunreliable results with this.

请注意,可以将实际的 xml 字符串放在命令行中,但我的结果非常不可靠。

Edit

编辑

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:

在很多帮助下,我现在明白我真正的问题是“如何将变量通过管道传递给 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;
}

回答by Savageman

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).

我不确定你想要达到的目标。您可以使用 URL php://stdin 读取标准输入。但那是来自 PHP 命令行的标准输入,而不是来自 pdftk(通过 exec)的标准输入。

But I'll give a +1 for proc_open()

但我会给+1 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;
}
?>

回答by Michael Mior

1) Why are you outputting to standard out and then putting that stuff into a file? Why not just have pdftk dump to the file, i.e.

1)为什么要输出到标准输出然后将这些东西放入文件中?为什么不直接将 pdftk 转储到文件中,即

exec("pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf");

2) Use proc_open(). Feel free to post any problems you have with the function.

2)使用proc_open()。随意发布您对该功能的任何问题。