php - 带有 php ://memory 的 PDFTK

标签 php pdftk

问题:是否可以在 execpassthru 命令上使用 php://memory

我可以在 exec 或 passthru 中使用 php 变量没有问题,但我在使用 php://memory 时遇到了问题

背景: 我正在尝试消除所有使用 PDFTK 编写的临时 pdf 文件。
1)我正在写一个临时的fdf文件
2) 使用 #1
填写临时 pdf 文件 3) 对所有 pdf 重复 #1 和 #2
4) 将所有 pdf 合并在一起。

这目前有效 - 但它会创建大量文件,并且是瓶颈。

我想通过使用虚拟文件 php://memory 来加快 pdftk 的速度

首先,我试图虚拟化 #1 中使用的 fdf 文件。
单独回答这个问题就足以获得“正确答案”。 :)

代码如下:

$fdf = 'fdf file contents here';
$tempFdfVirtual= fopen("php://memory", 'r+');
if(  $tempFdfVirtual ) {
  fwrite(  $tempFdfVirtual, $fdf);
} else {
    echo "Failure to open temporary fdf file";
    exit;
}
rewind( $tempFdfVirtual);
$url = "unfilled.pdf";
$temppdf_fn = "output.pdf"; 
$command = "pdftk $url fill_form  $tempFdfVirtual output $temppdf_fn flatten"; 
$error="";   
exec( $command, $error );
if ($error!="") {
    $_SESSION['err'] = $error;       
} else {
    $_SESSION['err'] = 0;
}

我收到错误代码#1。如果我执行 stream_get_contents($tempFdfVirtual),它会显示内容。

感谢您的关注!

最佳答案

php://memoryphp://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);

关于php - 带有 php ://memory 的 PDFTK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8978772/

相关文章:

php - 将 PHPT 测试用例与 PHPUnit 集成

php - 我如何在 MySQLi php 中使用 Join

php socket_accept 停止

php - 在 PHP 中将 XSD 模板转换为 XML 实例

php - Laravel 原始查询和 Eloquent ORM 关系

pdf - 在 PHP 中使用 utf-8 字符将 FDF/XFDF 表单展平为 PDF

PHPExcel 创建/样式化/保存 PDF 文档

python - 反向 PDF 拼版

ruby-on-rails - 如何设置 pdftk 或 iText 以在 Heroku 上使用 Rails 3?

linux - 如何在适用于 cPanel 或 CentOS 的 VPS 上安装 PDFTK?