2012-01-23 7 views
3

質問:のexecまたはパススルーコマンドに//メモリ:それはPHPを使用することは可能ですか?PDFTK://メモリ

私は何の問題もなく、EXECまたはパススルーでPHPの変数を使用することができますが、私は、PHPとのトラブルを抱えています:私は私の一時的なPDFファイルの書き込みの全てを排除しようとしています ://メモリ

背景をPDFTKで私は一時的なFDFファイルを書いています
1)
2)フォーム記入すべてのPDFファイル
4)一緒にすべてのPDFのをマージするために#1
3)リピート#1、#2を使用して、一時pdfファイルを。

これは現在動作していますが、多くのファイルが作成され、ボトルネックです。

私は仮想ファイルのPHPを利用することにより、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)を実行すると、コンテンツが表示されます。

ありがとうございます!

+0

だけFYI同じものを探してすることができる他の人に...私はステップ1を完了するために以下の回答を使用しました。私はその後、パイプに出力するpdftkと、次にすべての出力ストリームを1つのpdfにマージするZendPdfの組み合わせを使用してステップ2〜4を達成することができました。 PDFTKは、仮想PDFをマージする際に1つの仮想ストリームを受け入れることに限られていますが、実際のファイルのリストでは正常に動作します。 ZendPdfに関する素晴らしい点は、ファイル全体ではなくpdfデータを渡すことができることです。 – Cymbals

答えて

3

php://memoryおよびphp://temp(実際にはファイル記述子)は、現在実行されているPHPプロセスでのみ使用できます。また、$tempFdfVirtualはリソースハンドルなので、文字列に入れるのは意味がありません。

リソースハンドルからのデータを標準入力に渡す必要があります。 より、子プロセスへの入力と出力をより詳細に制御できるように、proc-openでこれを行うことができます。

「php:// memory」ファイル記述子を何らかの理由でプロセスに渡すことはできません。PHPは文句を言うでしょう:

警告:は、proc_open()を:それは使用する以外、まったく同じことになっているファイル記述子の代わりに

使用php://temp、として型メモリの流れを表すことができませんストリームが十分に大きくなると一時ファイルになります。

これは、proc_open()を使用するコードの一般的なパターンを示すテスト済みの例です。これは、関数または他の抽象化に包まれるべきである。PDFTKの使用に固有の

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

テストされていない例:

// 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); 
+0

私はproc_openを初めて使っています。私がproc_openにphp:// memory経由で作成したvirtualfdfファイルを渡したとき、私はproc_open()を取得しています。[function.proc-open]:MEMORY型のストリームをファイル記述子として表現できません。変数$ fdfに文字列が含まれている場合、stdoutを使って仮想ファイルを作成するか、proc_openに "file"を正しく渡す必要がありますか? – Cymbals

+0

私は$ tempFdfVirtual = fopen( "php:// stdout"、 'r +')を試みました。 – Cymbals

+0

ああ、それは深刻なバマーです。これはPHPの制限です。 'php:// memory'の代わりに' php:// temp'を使用してください。なぜ私のシステム上で動作するように見えますが、なぜ違いがあるのか​​わかりません。 –

1

php://memoryを使用しているだけではなく、どのファイルハンドルでもありません。ファイルハンドルは、現在のプロセスに対してのみ存在します。すべての意図と目的のために、あなたがfopenから戻ったハンドルは、スクリプトの外の他の場所に転送することはできません。

外部アプリケーションを使用している限り、一時ファイルを使用することはほとんどありません。あなたの唯一の他の選択肢は、データをstdin上のpdftkに渡し、stdout上の出力を取得することです(サポートしている場合)。私の知る限り、その種のディスクリプタ(stdin/stdout)へのアクセスで外部プロセスを呼び出す唯一の方法は、proc_openproc_ファミリの関数を使用しています。

+0

ありがとうございました - あなたの素早い応答が昨日私を別の方向に向けると、proc_openで読んでくれました。 – Cymbals

関連する問題