30

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

pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf

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

pdftk blankform.pdf fill_form - output -

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

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

    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)stdinPHPでストリームを設定して、そのストリームを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は行くための最良の方法、または少なくとも最も簡単です。これを理解するのに私は永遠にかかりました、そしてグーグルでの私の研究は他の人が苦労しているかもしれないことを示唆しているので、私は私の問題のために特に働いたコードを投稿します:

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

2 に答える 2

30

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

しかし、私は+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;
}
?>
于 2010-03-05T23:59:12.930 に答える
-1

1)なぜ標準出力に出力して、それをファイルに入れるのですか?pdftkをファイルにダンプしてみませんか?

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

2)を使用しproc_open()ます。関数に関する問題があれば、遠慮なく投稿してください。

于 2010-03-05T23:49:45.547 に答える