如何将变量作为stdin从PHP传递到命令行 [英] How to pass variables as stdin into command line from PHP

查看:1358
本文介绍了如何将变量作为stdin从PHP传递到命令行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个PHP脚本,使用 pdftk 应用程序将XFDF与PDF形式并将合并的PDF输出给用户。根据pdftk文档,我可以通过 stdin 传递表单数据,并将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 -

我有几个问题:

1)我有pdftk通过 stdout 使用xfdf文件(而不是 stdin ):

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

但是它创建的pdf已损坏,根据Adobe Reader和快速查看文件一个文本编辑器显示,至少,它不是设置行结束他们应该在哪里。我有一个由pdftk创建的相同的PDF,它输出到一个文件,并且pdf在文本编辑器看起来很好,所以我知道它不是pdftk输出不良数据。

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中设置 stdin 流,以便我可以使用该流作为我的输入为pdftk。从我在PHP文档上阅读的内容, stdin 是只读的,那么什么东西怎么进入这个流呢?

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?

理想情况下,我想保持这个简单,避免使用 proc_open()。我试图使用该功能,并不是非常成功,这可能是我的错,而不是函数的,但真的我的目标是简单的,我宁愿避免使用我不需要的鲁棒的函数。

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

只要一个头,就可以把实际的xml字符串在命令行,但我已经非常不可靠的结果。

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.

有了很多帮助,我现在明白我的真正问题是如何管道一个变量到PHP的命令行执行。显然proc_open是最好的因为我花了很长时间才能明白这一点,因为我对Google的研究表明,其他人可能在努力,我会发布专门为我的问题工作的代码:

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


推荐答案

你想达到的目标。你可以使用URL php:// stdin读取stdin。但是这是来自PHP命令行的stdin,而不是来自pdftk(通过exec)的stdin。

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

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

这篇关于如何将变量作为stdin从PHP传递到命令行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆