pdftkアプリを使用してXFDFをPDFフォームとマージし、マージされたPDFをユーザーに出力するPHPスクリプトを作成しようとしています。pdftkのドキュメントによると、フォームデータを経由で渡し、stdin
PDFを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)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は行くための最良の方法、または少なくとも最も簡単です。これを理解するのに私は永遠にかかりました、そしてグーグルでの私の研究は他の人が苦労しているかもしれないことを示唆しているので、私は私の問題のために特に働いたコードを投稿します:
$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;
}