标准接口

分段上传操作可以将超过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。