2013-08-22 45 views
6

PHP用のAWS 2.3.2 SDKを使用して、ストリームラッパーを使用してS3から大きなファイル(〜4g)をプルダウンしようとしています。 fopen/fwriteを使用してファイルをディスクに書き込み、バッファをメモリに書き込まないでください。ここでHerokuメモリエラーが発生し、S3から大きなファイルを読み込む

は参照です:ここでは

http://docs.aws.amazon.com/aws-sdk-php-2/guide/latest/service-s3.html#downloading-data

は私のコードです:

public function download() 
    { 

     $client = S3Client::factory(array(
        'key' => getenv('S3_KEY'), 
        'secret' => getenv('S3_SECRET') 
        )); 

     $bucket = getenv('S3_BUCKET'); 
     $client->registerStreamWrapper(); 

     try { 
      error_log("calling download"); 
      // Open a stream in read-only mode 
      if ($stream = fopen('s3://'.$bucket.'/tmp/'.$this->getOwner()->filename, 'r')) { 
       // While the stream is still open 
       if (($fp = @fopen($this->getOwner()->path . '/' . $this->getOwner()->filename, 'w')) !== false){ 

        while (!feof($stream)) { 
         // Read 1024 bytes from the stream 
         fwrite($fp, fread($stream, 1024)); 
        } 
        fclose($fp); 
       } 
      // Be sure to close the stream resource when you're done with it 
      fclose($stream); 
     } 

ファイルのダウンロードが、私は継続的にHerokuのからのエラーメッセージを取得:

2013- 08-22T19:57:59.537740 + 00:00英雄[run.9336]:プロセス実行 MEM = 515M(100.6パーセント)2013-08-22T19:57:59.537972 + 00:00 Herokuの[run.9336]: エラーR14これはまだあると信じて私をリード

を(メモリ割当て制限を超えました)メモリに何らかの形でバッファリングする。 https://github.com/arnaud-lb/php-memory-profilerを使用しようとしましたが、Segフォルトがあります。

私はまた、CURLOPT_FILEオプションを指定してcURLを使用してファイルをダウンロードしようとしましたが、ディスクに直接書き込むためにメモリが不足しています。奇妙なことは、topによると私のPHPインスタンスは223mのメモリを使用しているので、許可された512の半分でもありません。

他にもアイデアはありますか?私はこれをPHP 5.4.17からテストするために実行しています。

+0

また、php copyコマンドを試して、fflush($ fp)を使って書き込みバッファをフラッシュしてみました。これはメモリを使い果たしてはならない – bonez

+0

バイナリモードでファイルを読み書きする 'rb'と' wb'に変更できますか?また、これは何も変わるべきではありませんが、ただ確実にするために、読み書きの間にデータを保持するために一時変数を使用する場合、同じ結果が得られますか? – culix

+0

それは何も変わっていませんでした...クリアすることもできます:コマンドラインから - $ curl -O http://test.s3.amazonaws.com/file.zipでもメモリエラーが発生すると思います問題です。それは私が知らない間違ったエラーかもしれない、私はHerokuとのサポートリクエストを持っている – bonez

答えて

2

すでに2倍のdynoで試しましたか?それらは1GBのメモリを搭載していますか?

また、PHPでcurlコマンドを実行してファイルをダウンロードすることもできます。最もクリーンな方法ではありませんが、より高速で、より信頼性が高く、メモリにもやさしいでしょう。

exec("curl -O http://test.s3.amazonaws.com/file.zip", $output); 

この例は公開URLです。 S3ファイルを公開したくない場合は、署名付きのURLを作成し、curlコマンドと組み合わせて使用​​することができます。

+0

はい、その後取得します 2013-08-23T14:30:06.785538 + 00:00 heroku [run.7646]:プロセス実行mem = 1024M(100。2013-08-23T14:30:06.785658 + 00:00 heroku [run.7646]:エラーR14(メモリクォータを超えました) – bonez

+0

上記の編集済みの記事で説明したように、カールの実装を試してください。 –

+0

この実装と同じ結果を試してみてください: 2013-08-23T19:23:29.446439 + 00:00英雄[run.2306]:プロセス実行mem = 1024M(100.0%) 2013-08-23T19:23:29.447246+ 00:00 heroku [run.2306]:エラーR14(メモリクォータを超えました) – bonez

関連する問題