web-dev-qa-db-ja.com

PHP)からコマンドラインに変数をstdinとして渡す方法

pdftk アプリを使用してXFDFをPHPフォームとマージし、マージされたものを出力するPDFスクリプトを作成しようとしています。 PDFユーザーに。pdftkのドキュメントによると、フォームデータをstdin経由で渡し、PDFをに出力させることができます。 stdoutstream。コマンドラインからpdftkを使用する通常の、ファイルではないストリームの方法は次のとおりです。

_pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf
_

コマンドラインでストリームを使用するには、次のように入力します。

_pdftk blankform.pdf fill_form - output -
_

私にはいくつかの問題があります:

1)次のように(stdoutの代わりに)xfdfファイルを使用してstdin経由で出力を返すpdftkを取得しました。

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

しかし、Adobe Readerによると、作成されたpdfは破損しており、テキストエディターでファイルをざっと見ると、少なくとも、行末が本来あるべき場所に設定されていないことがわかります。私は同じPDF pdftkによって作成され、ファイルに出力します。pdfはテキストエディターで正常に表示されるので、悪いデータを出力しているのはpdftkではないことがわかります。

2)stdinストリームをPHPに設定して、そのストリームを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が最善の方法であるか、少なくとも最も簡単です。これを理解するのに永遠に時間がかかり、Googleでの調査で他の人が苦労している可能性があることがわかったので、私の問題に特に役立つコードを投稿します。

_$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;
}
_
28
Anthony

あなたが何を達成しようとしているのかわかりません。あなたはURLphp:// stdinでstdinを読むことができます。しかし、それはPHPコマンドラインからのstdinであり、pdftkからのstdinではありません(execを介して)。

しかし、私はproc_open()に+1を与えます


<?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;
}
?>
26
Savageman