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 が実現できれば。