Amazon S3にAWS SDK for PHP 2からMultipartUploadを試してみました。以下例は、5M単位で分割して送信を行うようになっています。回線負荷も分散が可能になります。createMultipartUpload → uploadParts → completeMultipartUploadで処理が行われます。uploadPartsは分割分処理が走ります。(Amazon S3はメディアファイルの配信には最適。)
require_once("AWSSDKforPHP/aws.phar");
use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Guzzle\Http\EntityBody;
use Aws\Common\Exception\MultipartUploadException;
use Aws\S3\Model\MultipartUpload\UploadBuilder;
$access_key = 'access key';
$secret_key = 'secret key';
$region = Region::AP_NORTHEAST_1; // Region::AP_NORTHEAST_1 = Tokyo Region
$end_point_url = 'http://str.cloudn-service.com';
$bucket = 'xxxx';
try {
// S3
$s3 = Aws::factory(array(
'key' => $access_key,
'secret' => $secret_key,
'region' => $region,
// 'base_url' => $end_point_url,
))->get('s3');
$info = new FInfo(FILEINFO_MIME_TYPE);
// Upload File
$filename = "sample.mp4";
$body = EntityBody::factory(fopen($filename, 'r'));
$filetype = $info->file($filename);
$key = "test" . time();
$response = $s3->createMultipartUpload(array(
'Bucket' => $bucket,
'Key' => $key
));
$uploadId = $response['UploadId'];
echo('createMultipartUpload: Finished with id: ' . $uploadId);
$chunkSize = 5242880;
$start = 0;
$part = 0;
$length = $body->getSize();
while($start < $length) {
$end = $start + $chunkSize;
if($end > $length)
$end = $length;
$body->seek($start);
$body->setSize($end);
$real_chunk_size = $end - $start;
var_dump('Sending part #'. $part . ' containing '.$start.' through '. $end . ' of ' . $length);
$response = $s3->uploadPart(array(
'Bucket' => $bucket,
'Key' => $key,
'Body' => $body->read($real_chunk_size),
'PartNumber' => (string)$part+1,
'UploadId' => $uploadId,
'ContentMD5' => hash_file('md5', $filename)
));
$etag = $response->getPath('ETag');
$requestId = $response->getPath('RequestId');
var_dump('Part Received with Etag: '.$etag.' and RequestId: ' .$requestId);
$part++;
$start += $chunkSize;
}
$parts = $s3->listParts(array(
'Bucket' => $bucket,
'Key' => $key,
'UploadId' => $uploadId,
));
$s3->completeMultipartUpload(array(
'Bucket' => $bucket,
'Key' => $key,
'UploadId' => $uploadId,
'Parts' => $parts['Parts']
));
var_dump('Done');
} catch (S3Exception $e) {
$s3->abortMultipartUpload(array(
'Bucket' => $bucket,
'Key' => $key,
'UploadId' => $uploadId
));
S3互換を歌っているCloudnのObjectStorageへのMultipartUploadを試しているのだが、completeMultipartUploadで例外が発生。
putObjectでは問題なくアップロードが完了するので、MultipartUploadの設定ではと考えれる。
あとは、Browser Based Uploaded Using POST が実現できれば。