php://memory
и php://temp
(и фактически любой дескриптор файла) доступны только для запущенного в настоящее время процесса php. Кроме того, $tempFdfVirtual
является дескриптором ресурса, поэтому нет смысла помещать его в строку.
Вы должны передать данные из вашего дескриптора ресурса в процесс через его стандартный вход. Вы можете сделать это с помощью proc-open
, что дает вам больший контроль над вводом и выводом дочернего процесса, чем exec
.
Обратите внимание, что по какой-то причине вы не можете передать дескриптор файла 'php: // memory' процессу. PHP будет жаловаться:
Предупреждение: proc_open (): не может представлять поток типа MEMORY в качестве дескриптора файла
Вместо этого используйте php://temp
, который должен быть точно таким же, за исключением того, что он будет использовать временный файл, как только поток станет достаточно большим.
Это проверенный пример, который иллюстрирует общий шаблон кода, который использует proc_open()
. Это должно быть заключено в функцию или другую абстракцию:
$testinput = "THIS IS A TEST STRING\n";
$fp = fopen('php://temp', 'r+');
fwrite($fp, $testinput);
rewind($fp);
$cmd = 'cat';
$dspec = array(
0 => $fp,
1 => array('pipe', 'w'),
);
$pp = proc_open($cmd, $dspec, $pipes);
// busywait until process is finished running.
do {
usleep(10000);
$stat = proc_get_status($pp);
} while($stat and $stat['running']);
if ($stat['exitcode']===0) {
// index in $pipes will match index in $dspec
// note only descriptors created by proc_open will be in $pipes
// i.e. $dspec indexes with an array value.
$output = stream_get_contents($pipes[1]);
if ($output == $testinput) {
echo "TEST PASSED!!";
} else {
echo "TEST FAILED!! Output does not match input.";
}
} else {
echo "TEST FAILED!! Process has non-zero exit status.";
}
// cleanup
// close pipes first, THEN close process handle.
foreach ($pipes as $pipe) {
fclose($pipe);
}
// Only file descriptors created by proc_open() will be in $pipes.
// We still need to close file descriptors we created ourselves and
// passed to it.
// We can do this before or after proc_close().
fclose($fp);
proc_close($pp);
Непроверенный пример, специфичный для вашего использования PDFTK:
// Command takes input from STDIN
$command = "pdftk unfilled.pdf fill_form - output tempfile.pdf flatten";
$descriptorspec = array(
0 => $tempFdfVirtual, // feed stdin of process from this file descriptor
// 1 => array('pipe', 'w'), // Note you can also grab stdout from a pipe, no need for temp file
);
$prochandle = proc_open($command, $descriptorspec, $pipes);
// busy-wait until it finishes running
do {
usleep(10000);
$stat = proc_get_status($prochandle);
} while ($stat and $stat['running']);
if ($stat['exitcode']===0) {
// ran successfully
// output is in that filename
// or in the file handle in $pipes if you told the command to write to stdout.
}
// cleanup
foreach ($pipes as $pipe) {
fclose($pipe);
}
proc_close($prochandle);