php://memory和php://temp(实际上任何文件描述符)仅适用于当前运行的php进程。此外,$tempFdfVirtual是一个资源句柄,因此将它放在字符串中是没有意义的。
您应该通过标准输入将资源句柄中的数据传递给进程。您可以使用proc-open执行此操作,这使您可以更好地控制子进程的输入和输出,而不是exec。
请注意,由于某种原因,您无法将“php:// memory”文件描述符传递给进程。 PHP会抱怨:
Warning: proc_open(): cannot represent a stream of type MEMORY as a File Descriptor
使用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);