PHP和从S3读取大文件时出现Heroku内存错误


Heroku Memory Error with PHP and reading large file from S3

我正在使用AWS 2.3.2 SDK for PHP,试图使用流包装器从S3中提取一个大文件(~4g),这应该允许我使用fopen/fwrite将文件写入磁盘,而不是缓冲区写入内存。

以下是参考资料:

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

这是我的代码:

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+000:00 heroku[run.9336]:进程运行mem=515M(100.6%)2013-08-22T19:17:59.537972+00:0 heroku[运行.9336]:错误R14(超出内存配额)

这让我相信这仍然在缓冲记忆。我试过用https://github.com/arnaud-lb/php-memory-profiler,但有Seg故障。

我还尝试使用带有CURLOPT_file选项的cURL下载文件,直接写入磁盘,但我的内存仍然不足。奇怪的是,根据top,我的php实例使用了223m的内存,所以甚至还不到允许的512的一半。

有人有什么想法吗?我从php 5.4.17 cli运行这个来进行测试。

你已经尝试过使用2x dyno了吗?它们有1GB的内存?

您还可以尝试通过在PHP中执行curl命令来下载文件。这不是最干净的方式,但它会更快/更可靠,并且对内存友好。

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

此示例适用于公共URL。如果您不想公开S3文件,您可以创建一个签名的URL,并将其与curl命令结合使用。