PHP
AWS
S3
AWS-SDK-for-PHP

aws-sdk-phpで5GB以上のファイルをS3にアップロードする方法

何の話?

S3に5GB以上のファイルを、aws-sdk-phpのS3のputObjectを使ってアップロードしようとしたら、以下のエラーが出た。

1ファイルあたりのアップロードできる上限サイズは、5368709120byte(5.36870912GB)なのに、
5506553726byte(5.506553726GB)アップロードしようとしてると怒られている。

Error executing "PutObject" on "https://xxxx.s3.ap-northeast-1.amazonaws.com/path/filename"; 
AWS HTTP error: Client error: `PUT https://xxxx.s3.ap-northeast-1.amazonaws.com/path/filename` resulted in a `400 Bad Request` 
<?xml version='1.0' encoding='utf-8'?>
<error>
    <code>
        EntityTooLarge
    </code>
    <message>
        Your proposed upload exceeds the maxim (truncated...)
    EntityTooLarge (client): Your proposed upload exceeds the maximum allowed size -
        <?xml version='1.0' encoding='utf-8'?>
    </message>
</error>
<error>
    <code>
        EntityTooLarge
    </code>
    <message>
        Your proposed upload exceeds the maximum allowed size
    </message>
    <proposedsize>
        5506553726
    </proposedsize>
    <maxsizeallowed>
        5368709120
    </maxsizeallowed>
    <requestid>
        DCB569101CF240C0
    </requestid>
    <hostid>
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    </hostid>
</error>

AWSのよくある質問を見ると

Q: どれほどの量のデータを保存できますか?

格納可能なデータの総量とオブジェクトの数には制限はありません。個別の Amazon S3 オブジェクトのサイズは、最低 0 バイトから最大 5 テラバイトまでさまざまです。1つの PUT にアップロード可能なオブジェクトの最大サイズは 5 GB です。100 MB 以上のオブジェクトの場合は、Multipart Upload 機能を使うことをお考えください。

https://aws.amazon.com/jp/s3/faqs/

総量とオブジェクトの数には制限はないが、1つの PUT にアップロード可能なオブジェクトの最大サイズは 5 GBらしい。
100 MB 以上のオブジェクトの場合は、Multipart Upload 機能を使うことをお考えください、とある。

MultipartUploaderとは

以下のサイトにMultipartUploaderを使って、5GB以上のファイルでもアップロードする方法が書いてある。
最大5TBのファイルまでアップロードできるらしい。
Amazon S3 オブジェクトのサイズの上限までってことか。

With a single PutObject operation, you can upload objects up to 5 GB in size. However, by using the multipart uploads (e.g., CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload), you can upload object up to 5 TB in size.

Amazon S3 Multipart Uploads

MultipartUploaderを使ってみる

composer

aws-sdk-phpがインストールされていることが前提。
composer以外の方法でインストールしてもOK。

composer.json
{
    "autoload": {
        "psr-4": {
        }
    },
    "require": {
        "aws/aws-sdk-php": "3.*"
    }
}

PHPのソースを作成

以下のソースで、5GB以上のファイルもアップロードできた。

<?php

require(dirname(__FILE__) . '/vendor/autoload.php');

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

$s3Client = S3Client::factory([
    'version' => '2006-03-01',
    'key' => 'xxxxxxxx',
    'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'region' => 'ap-northeast-1'
]);


$bucketname = 'sample-bucket';
$from_path = './bigdata.csv';
$to_path = 'dirname/bigdata.csv';

$uploader = new MultipartUploader($s3Client, $from_path, [
    'bucket' => $bucketname,
    'key'    => $to_path,
]);

try {
    $result = $uploader->upload();
    print_r($result);
    echo $result['ObjectURL'];
} catch (MultipartUploadException $e) {
    echo $e->getMessage();
}

以上