AWS s3分段上传失败+内存分配耗尽+ php

时间:2016-03-31 13:10:40

标签: php amazon-web-services amazon-s3 memory-leaks

我正在尝试将大约9GB的视频从我的服务器上传到s3输入。我在服务器上有4GB RAM。我正在使用http://docs.aws.amazon.com/aws-sdk-php/v2/api/class-Aws.S3.S3Client.html#_completeMultipartUpload

我也在脚本中将memory_limit设置为4GB。但它仍然失败并抛出内存耗尽错误 - 试图分配内存bla bla bla ..我发现的是 https://www.eldos.com/forum/read.php?FID=7&TID=6331

有没有解决方案可以解决这个问题? 。以下是我的示例代码。 我正在使用laravel 5.1并使用

$ client = App :: make(' aws') - > createClient(' s3');

    try {

        $response = $client->createMultipartUpload(array(
            'Bucket' => $bucket,
            'Key' => $fileName
        ));
        $uploadId = $response['UploadId'];
        // 3. Upload the file in parts.
        $file = fopen(public_path('videos') . '/' . $fileName, 'r');
        $parts = array();
        $partNumber = 1;
        while (!feof($file)) {

            $result = $client->uploadPart(array(
                'Bucket' => $bucket,
                'Key' => $fileName,
                'UploadId' => $uploadId,
                'PartNumber' => $partNumber,
                'Body' => fread($file, 2 * 1024 * 1024),
            ));
            $parts[] = array(
                'PartNumber' => $partNumber++,
                'ETag' => $result['ETag'],
            );
        }
        // 4. Complete multipart upload.
        $result = $client->completeMultipartUpload(array(
            'Bucket' => $bucket,
            'Key' => $fileName,
            'UploadId' => $uploadId,
            'MultipartUpload' => Array(
                'Parts' => $parts,
            ),
        ));

        return $fileName;
    }
    catch (\Aws\S3\Exception\S3Exception $e) {
        $result = $client->abortMultipartUpload(array(
            'Bucket' => $bucket,
            'Key' => $fileName,
            'UploadId' => $uploadId
        ));
        throw new Exception($e->getMessage(), NULL, NULL);
    }
Thanks

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,我花了一段时间,因为我必须学习以下内容:

  • AWS SDK for php
  • 中有一个低级API
  • AWS SDK for php
  • 中有一个高级API
  • 野外有不同的文件

您在寻找什么,是这样的: http://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-multipart-upload.html

Workig代码示例(来自该文档):

use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;

$uploader = new MultipartUploader($s3Client, '/path/to/large/file.zip', [
    'bucket' => 'your-bucket',
    'key'    => 'my-file.zip',
]);

try {
    $result = $uploader->upload();
    echo "Upload complete: {$result['ObjectURL']}\n";
} catch (MultipartUploadException $e) {
    echo $e->getMessage() . "\n";
}

低级API(在您的示例中)不起作用,因为它创建所选块大小的临时文件以及占用内存(甚至您销毁s3_client对象)。

在我的情况下,我确实最终陷入了(非捕获)致命内存异常,在S3存储上有一个完整的磁盘和部分上传的文件(由于存储使用而需要花钱)但是没有在正常的s3存储桶中列出(参见:http://www.deplication.net/2016/06/aws-tip-save-s3-costs-with-abort.html

这个例子使用了对我来说很好的高级api并且有一个小的食物印记。

您不使用的链接:

  • docs.aws.amazon.com/AmazonS3/latest/dev/usingHLmpuPHP.html
  • docs.aws.amazon.com/AmazonS3/latest/dev/LLuploadFilePHP.html