working shell_exec script passthru not example ejemplos ejecutar desde php command-line stream stdin pdftk

shell_exec - php system



Cómo pasar variables como stdin a la línea de comandos desde PHP (2)

1) ¿Por qué estás saliendo a la salida estándar y luego metes esas cosas en un archivo? ¿Por qué no solo tener pdftk dump al archivo, es decir

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

2) Utilice proc_open() . Siéntase libre de publicar cualquier problema que tenga con la función.

Estoy intentando escribir un script PHP que usa la aplicación pdftk para combinar un XFDF con un formulario PDF y enviar el PDF combinado al usuario. De acuerdo con la documentación de pdftk, puedo pasar los datos del formulario a través de la stdin y tener la salida de PDF a la secuencia de la salida stdin . La forma normal de usar el archivo pdftk desde la línea de comandos es:

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

para usar streams en la línea de comando, debe ingresar:

pdftk blankform.pdf fill_form - output -

Tengo un par de problemas:

1) He conseguido que pdftk devuelva la salida a través de stdout usando un archivo xfdf (en lugar de stdin ) como tal:

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

Pero el pdf que crea está dañado, según Adobe Reader y un vistazo rápido al archivo con un editor de texto muestra que, al menos, no está configurando los finales de línea donde deberían estar. Tengo un PDF idéntico creado por pdftk donde se envía a un archivo, y el pdf se ve bien en el editor de texto, así que sé que no es pdftk lo que genera datos incorrectos.

2) No puedo, por mi vida, descubrir cómo configurar el flujo stdin en PHP para que pueda usar ese flujo como mi entrada para pdftk. Por lo que estoy leyendo en la documentación de PHP, stdin es de solo lectura, así que, ¿cómo llega algo a esa secuencia?

Idealmente, me gustaría mantener esto realmente simple y evitar el uso de proc_open() . Intenté usar esa función y no tuve mucho éxito, lo cual es probablemente mi culpa, no la función, pero en realidad mis objetivos son lo suficientemente simples. Prefiero evitar el uso de funciones robustas que no necesito.

Idealmente mi código se vería algo así como:

$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 -);

Solo un aviso, es posible colocar la cadena xml real en la línea de comandos, pero con esto he tenido resultados muy poco confiables.

Editar

Con mucha ayuda, ahora entiendo que mi pregunta real era "¿cómo se puede canalizar una variable a una ejecución de línea de comandos en PHP". Al parecer, proc_open es la mejor manera de ir, o al menos la más sencilla. Ya que me llevó una eternidad resolver esto y como mi investigación en Google sugiere que otros pueden estar teniendo problemas, publicaré el código que funcionó específicamente para mi problema:

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


No estoy seguro de lo que estás tratando de lograr. Puedes leer stdin con la URL php: // stdin. Pero ese es el stdin de la línea de comandos de PHP, no el de pdftk (a través de exec).

Pero le daré un +1 para 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; } ?>