Я пытаюсь записать Сценарий PHP, который использует pdftk приложение, чтобы объединить XFDF с формой PDF и произвести объединенный PDF пользователю. Согласно pdftk документации, я могу передать данные формы на пути stdin
и произведите PDF к stdout
поток. Нормальное, file-not-stream способ использовать pdftk из командной строки:
pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf
для использования потоков на командной строке Вы вошли бы:
pdftk blankform.pdf fill_form - output -
У меня есть несколько проблем:
1) Я заставил pdftk возвращать вывод через stdout
использование xfdf файла (вместо stdin
) как так:
exec("pdftk blankform.pdf fill_form formdata.xfdf output -", $pdf_output);
file_put_contents("filledform.pdf",$pdf_output);
Но PDF, который это создает, поврежден, по данным Adobe Reader, и быстрый быстрый взгляд на файл с текстовым редактором показывает, что по крайней мере это не устанавливает окончания строки, где они должны быть. Мне создал идентичный 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;
}
Я не уверен в том, чего вы пытаетесь достичь. Вы можете читать стандартный ввод с помощью URL-адреса php: // stdin. Но это стандартный ввод из командной строки PHP, а не из pdftk (через exec).
Но я дам +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;
}
?>
1) Почему вы выводите данные в стандартный вывод, а затем помещаете их в файл? Почему бы просто не сделать дамп pdftk в файл, т.е.
exec("pdftk blankform.pdf fill_form formdata.xfdf output filledform.pdf");
2) Используйте proc_open()
. Не стесняйтесь публиковать любые проблемы, которые у вас возникли с этой функцией.