标准接口
分段上传操作可以将超过5GB的大文件分割后上传,一共包含三个步骤:首先,发起分段上传请求获取一个upload id。然后,将大文件分割成片段后上传,除了最后一个片段,每个片段的数据大小为5MB~5GB,每个片段上传的时候附带upload id。最后,发送一个带有upload id的请求,完成或者中止分段上传操作。
代码示例:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
namespace DotNetSDK.ObjectOperation
{
public class UploadPartExample
{
public static async Task UploadPart()
{
var accessKey = "YOUR_ACCESS_KEY";
var secretKey = "YOUR_SECRET_KEY";
var endpoint = "YOUR_ENDPOINT";
var bucketName = "EXAMPLE_BUCKET";
var key = "EXAMPLE_KEY";
var filePath = "LOCAL_FILE_PATH";
try
{
var credentials = new BasicAWSCredentials(accessKey, secretKey);
var conf = new AmazonS3Config
{
ServiceURL = endpoint
};
var s3Client = new AmazonS3Client(credentials, conf);
//1. 发起一个分段上传操作请求,获取upload id
var initiateMultipartUploadRequest = new InitiateMultipartUploadRequest()
{
BucketName = bucketName,
Key = key
};
var initiateMultipartUploadResponse = await s3Client.InitiateMultipartUploadAsync(initiateMultipartUploadRequest);
var uploadId = initiateMultipartUploadResponse.UploadId;
Console.WriteLine("upload id: {0}", uploadId);
// 2. 分割大文件然后分段上传
var partSize = 1024 * 1024 * 16;
var fileInfo = new FileInfo(filePath);
var fileLen = fileInfo.Length;
var partNumber = fileLen / partSize;
if (fileLen % partSize != 0)
{
partNumber++;
}
var etagList = new List<PartETag>();
using (var fs = File.Open(filePath, FileMode.Open))
{
for (var i = 0; i < partNumber; i++)
{
var seekBytes = (long) partSize * i;
fs.Seek(seekBytes, 0);
var size = (partSize < fileLen - seekBytes) ? partSize : (fileLen - seekBytes);
var uploadPartRequest = new UploadPartRequest()
{
BucketName = bucketName,
Key = key,
UploadId = uploadId,
InputStream = fs,
PartSize = size,
PartNumber = i + 1
};
// 分片上传
var uploadPartResponse = await s3Client.UploadPartAsync(uploadPartRequest);
etagList.Add(new PartETag(uploadPartResponse.PartNumber, uploadPartResponse.ETag));
Console.WriteLine("finish upload part {0}/{1}", etagList.Count, partNumber);
}
}
// 3. 完成分段上传
var completeMultipartUploadRequest = new CompleteMultipartUploadRequest()
{
BucketName = bucketName,
Key = key,
UploadId = uploadId
};
foreach (var etag in etagList)
{
completeMultipartUploadRequest.PartETags.Add(etag);
}
var completeMultipartUploadResponse = await s3Client.CompleteMultipartUploadAsync(completeMultipartUploadRequest);
if (completeMultipartUploadResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
{
Console.WriteLine("fail to complete multipart upload, HttpStatusCode:{0}, ErrorCode:{1}.", (int) completeMultipartUploadResponse.HttpStatusCode,
completeMultipartUploadResponse.HttpStatusCode);
}
else
{
Console.WriteLine("complete multipart upload.");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
InitiateMultipartUpload 用于创建分片上传任务,返回分片上传任务的ID。
可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
CannedACL | S3CannedACL | 配置上传对象的预定义的标准ACL信息。 | 否 |
BucketName | string | bucket的名称。 | 是 |
ContentType | string | 描述上传文件格式的标准MIME类型。 | 否 |
Key | string | 上传文件到媒体存储服务后对应的key。 | 是 |
Metadata | MetadataCollection | 本次请求附带的元数据信息。 | 否 |
TagSet | List<Tag> | 对象的标签信息。 | 否 |
WebsiteRedirectLocation | string | 如果bucket被配置用于提供网站的静态数据,该参数可以用于设置访问对象时候重定向到当前bucket下的其他对象或者外部的URL。 | 否 |
返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
AbortDate | DateTime | 如果bucket配置了管理未完成的上传分段的生命周期管理规则,并且该规则对本次分段上传生效,则AbortDate返回表示终止本次分段上传的时间。 |
AbortRuleId | string | 当返回结果中包含AbortDate属性时,AbortRuleId表示使终止本次分段上传操作生效的生命周期管理规则的Id。 |
BucketName | string | 执行分段上传的bucket的名称。 |
Key | string | 本次分段上传对象的名称。 |
UploadId | string | 本次分段上传操作Id。 |
UploadPart用于获取到分片任务ID之后,通过ID来上传分片内容到S3服务器。
可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
InputStream | Stream | 对象的数据。 | 是 |
BucketName | string | bucket的名称。 | 是 |
PartSize | long | 说明请求body的长度(单位:字节),该参数可以在body长度不能被自动识别的情况下设置。 | 否 |
MD5Digest | string | 上传对象数据的base64编码的128位MD5值,不包含请求头部的信息。 | 否 |
Key | string | 上传文件到媒体存储服务后对应的key。 | 是 |
PartNumber | int | 说明当前数据在文件中所属的片段,大于等于1,小于等于10000。 | 是 |
UploadId | string | 通过InitiateMultipartUpload操作获取的UploadId,与一个分段上传的对象对应。 | 是 |
返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
ETag | string | 本次上传片段后对应的Entity Tag。 |
PartNumber | int | 分段上传数据在文件中所属的片段。 |
完成所有分片的上传之后,调用完成接口CompleteMultipartUpload,服务端会把所有分片合并成对象保存。
可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
BucketName | string | 执行分段上传的bucket的名称。 | 是 |
Key | string | 上传文件到媒体存储服务后对应的key。 | 是 |
PartETags | List<PartETag> | 包含了每个已上传的片段的ETag和PartNUmber等信息。 | 否 |
UploadId | string | 通过CreateMultipartUpload操作获取的UploadId,与一个对象的分段上传对应。 | 是 |
返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
BucketName | string | 执行分段上传的bucket的名称。 |
ETag | string | 本次上传对象后对应的Entity Tag。 |
Key | string | 上传文件到媒体存储服务后对应的key。 |
Location | string | 上传对象后对应的URI。 |
VersionId | string | 上传对象后相应的版本id。 |