代码之家  ›  专栏  ›  技术社区  ›  Anthony

如何将变量作为stdin从php传递到命令行

  •  27
  • Anthony  · 技术社区  · 16 年前

    我正在尝试编写一个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)我已经让pdftk通过 标准输出 使用xfdf文件(而不是 斯坦丁 像这样:

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

    但据adobe reader称,它创建的pdf文件已经损坏,使用文本编辑器快速查看该文件可以发现,至少,它并没有将行尾设置在应有的位置。我有一个由pdftk创建的相同的pdf,它输出到一个文件中,并且pdf在文本编辑器中看起来很好,所以我知道输出错误数据的不是pdftk。

    2)我一辈子都不知道如何设置 斯坦丁 在php中的流,以便我可以使用该流作为pdftk的输入。从我阅读的php文档来看, 斯坦丁 是只读的,那么怎么会有东西进入这个流呢?

    理想情况下,我希望保持这一点非常简单,避免使用 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;
    }
    
    2 回复  |  直到 16 年前
        1
  •  26
  •   Savageman    16 年前

    我不知道你想达到什么目的。您可以使用url php://stdin阅读stdin。但这是php命令行中的stdin,而不是pdftk(通过exec)中的stdin。

    但我会给一个+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;
    }
    ?>
    
        2
  •  -1
  •   Michael Mior Aouidane Med Amine    16 年前

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

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

    2)使用 proc_open() . 如果你在这个功能上有任何问题,请随时发布。