2013-08-22 33 views
6

我正在使用PHP的AWS 2.3.2 SDK尝试从S3中使用它们的流包装器拉下一个大文件(〜4g),这应该允许我使用fopen/fwrite将文件写入磁盘,而不是缓冲到内存中。Heroku内存错误与PHP和从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 heroku [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 Fault。

我也尝试使用cURL和CURLOPT_FILE选项下载文件直接写入磁盘,并且内存不足。奇怪的是根据top我的php实例正在使用223m的内存,所以甚至没有允许的一半512.

任何人有任何想法?我从php 5.4.17 cli运行这个测试。

+0

也尝试了PHP复制命令,并使用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。0%) 2013-08-23T14:30:06.785658 + 00:00 heroku [run.7646]:错误R14(超出内存配额) – bonez

+0

也许你应该尝试卷曲实现,就像我在上面编辑过的帖子中解释过的那样。 –

+0

试过执行结果和相同结果: 2013-08-23T19:23:29.446439 + 00:00 heroku [run.2306]:进程运行mem = 1024M(100.0%) 2013-08-23T19:23:29.447246+ 00:00 heroku [run.2306]:错误R14(超出内存配额) – bonez