标准接口
简单上传方式只能上传小于5GB的对象,如果需要上传超过5GB的对象,您必须使用分片上传模式。此外,您也可以在如下的应用场景内(但不仅限于此),使用分片上传模式:
- 上传超过100MB大小的文件。
- 上传文件之前,无法确定上传文件的大小。
- 需要较高的吞吐量(采用并发上传分片)。
- 网络条件较差,和服务器之间的链接经常断开。
使用分片上传时,需要分为如下3个步骤:
- 初始化一个分片上传任务,使用 createMultipartUpload 接口
- 使用 UploadPart 接口上传分片
- 完成分片上传,使用 CompleteMultipartUpload 接口
使用Multipart Upload模式传输数据前,必须先初始化一个Multipart Upload事件,Multipart Upload事件可用于上传或复制对象。该操作会返回一个服务器创建的全局唯一的Upload ID,用于标识本次Multipart Upload事件。用户可以根据这个ID来发起相关的操作,如中止Multipart Upload、查询Multipart Upload等。
$bucket = '<your-bucket-name>';
$keyname = '<your-object-key>';
$file_Path = '<your-file-path>';
//指定桶与对象名,与上传对象类似,可以同时设置ACL
$result = $s3->createMultipartUpload([
'Bucket' => $bucket,
'Key' => $keyName,
]);
//在返回的result中获取用于区分分片上传的唯一标识UploadId,后续的操作中会使用该UploadId
$uploadId = $result['UploadId'];
初始化一个Multipart Upload之后,可以根据指定的对象名和Upload ID来分片(Part)上传数据。每一个上传的Part都有一个标识它的号码——分片号(part number,范围是1~10000)。对于同一个Upload ID,该分片号不但唯一标识这一块数据,也标识了这块数据在整个文件内的相对位置,您需要在 uploadPart 时指定Upload ID与分片号。如果用同一个分片号码,上传了新的数据,那么已有的这个分片的数据将被覆盖。除了最后一块part以外,其他的part最小为5MB;最后一块part没有大小限制。分片不需要按顺序上传,甚至可以在不同进程、不同机器上上传,在完成分片上传后服务端会按照分片号排序组成大文件。上传分片部分代码如下:
$file = fopen($filename, 'r');
$partNumber = 1;
while (!feof($file)) {
// 创建分片复制请求
$result = $s3->uploadPart([
'Bucket' => $bucket,
'Key' => $keyName,
'UploadId' => $uploadId, //uploadId从createMultipartUpload返回值获取
'PartNumber' => $partNumber, //设置分片号
'Body' => fread($file, 5 * 1024 * 1024), //读取文件分片,分片大小为5M
]);
$parts['Parts'][$partNumber] = [
// 记录ETag
'PartNumber' => $partNumber,
'ETag' => $result['ETag'],
];
echo "Uploading part {$partNumber} of {$filename}." . "\n";
$partNumber++;
}
fclose($file);
所有分片上传或复制完成后,需要调用 complete Multipart Upload 来完成整个文件的 Multipart Upload。在执行该操作时,需要提供所有有效的分片列表(包括分片号和分片 ETAG );服务端收到提交的分片列表后,会逐一验证每个分片的有效性。当所有的数据Part验证通过后,服务端将把这些分片组合成一个完整的 Object。完成分片上传示例代码如下:
$result = $s3->completeMultipartUpload([
'Bucket' => $bucket,
'Key' => $keyName,
'UploadId' => $uploadId,
'MultipartUpload' => $parts,
]);