融合接口
SDK提供封装好的融合接口,方便用户实现分片上传的功能。
接口定义
public void Upload(string filePath, string bucketName, string key);
public void Upload(Stream stream, string bucketName, string key);
public void Upload(TransferUtilityUploadRequest request);
public Task UploadAsync(string filePath, string bucketName, string key, CancellationToken cancellationToken = default);
public Task UploadAsync(Stream stream, string bucketName, string key, CancellationToken cancellationToken = default);
public Task UploadAsync(TransferUtilityUploadRequest request, CancellationToken cancellationToken = default);
代码示例
class TransDemo
{
private readonly AmazonS3Client s3Client;
private readonly TransferUtility utility;
private string bucket = "<your-bucket-name>";
public TransDemo()
{
var credentials = new BasicAWSCredentials("<your-access-key>", "<your-secret-key>");
var conf = new AmazonS3Config
{
ServiceURL = "<your-endpoint>",
};
this.s3Client = new AmazonS3Client(credentials, conf);
this.utility = new TransferUtility(this.s3Client);
}
public void UploadFile()
{
Console.Out.WriteLine("UploadFile");
var key = "<your-object-key>";
var filePath = "<file-path>";
this.utility.Upload(filePath, bucket, key);
Console.Out.WriteLine("UploadFile success");
}
public void UploadFileRequest()
{
Console.Out.WriteLine("UploadFileRequest");
var key = "<your-object-key>";
var filePath = "<file-path>";
TransferUtilityUploadRequest req = new TransferUtilityUploadRequest();
req.BucketName = this.bucket;
req.Key = key;
//req.FilePath = filePath;
req.InputStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
req.PartSize = 5 * 1024 * 1024;
req.CannedACL = S3CannedACL.PublicRead;
this.utility.Upload(req);
Console.Out.WriteLine("UploadFileRequest success");
}
}
请求参数
参数名 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucketName | string | 桶名 | 是 |
key | string | 要上传的对象名称 | 是 |
filePath | string | 上传的文件路径(和stream二选一) | 否 |
stream | Stream | 上传的文件流(和filePath二选一) | 否 |
TransferUtilityUploadRequest主要参数:
参数名 | 类型 | 说明 | 是否必要 |
---|---|---|---|
BucketName | string | 桶名 | 是 |
Key | string | 要上传的对象名称 | 是 |
FilePath | string | 上传的文件路径(和InputStream二选一) | 否 |
InputStream | Stream | 上传的文件流(和FilePath二选一) | 否 |
PartSize | long | 分片大小,默认5MB | 否 |
ContentType | string | 描述上传文件格式的标准MIME类型 | 否 |
CannedACL | S3CannedACL | 标准ACL信息(Private|PublicRead) | 否 |
关于Content-Type的配置
Content-Type用于标识文件的资源类型,比如image/png
, image/jpg
是图片类型,video/mpeg
, video/mp4
是视频类型,text/plain
, text/html
是文本类型, 浏览器针对不同的Content-Type会有不同的操作,比如图片类型可以预览,视频类型可以播放,文本类型可以直接打开。application/octet-stream
类型会直接打开下载窗口。
在dotnet sdk中,如果用户没有设置Content-Type,会根据对象的key后缀扩展名自动生成Content-Type。
上传分片
功能说明
分片上传操作可以将超过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-access-key>";
var endpoint = "<your-endpoint>";
var bucketName = "<your-bucket-name>";
var key = "<your-object-key>";
var filePath = "<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 | 桶的名称 | 是 |
ContentType | string | 描述上传文件格式的标准MIME类型 | 否 |
Key | string | 上传文件到媒体存储服务后对应的key | 是 |
Metadata | MetadataCollection | 本次请求附带的元数据信息 | 否 |
TagSet | List<Tag> | 对象的标签信息 | 否 |
WebsiteRedirectLocation | string | 如果桶被配置用于提供网站的静态数据,该参数可以用于设置访问对象时候重定向到当前桶下的其他对象或者外部的URL | 否 |
返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
BucketName | string | 执行分片上传的桶的名称 |
Key | string | 本次分片上传对象的名称 |
UploadId | string | 本次分片上传操作Id |
上传一个分片
UploadPart用于获取到分片任务upload id之后,通过upload id来上传分片数据到指定的分片上传任务对应的对象。
可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
InputStream | Stream | 对象的数据 | 是 |
BucketName | string | 桶的名称 | 是 |
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 | 执行分片上传的桶的名称 | 是 |
Key | string | 上传文件到媒体存储服务后对应的key | 是 |
PartETags | List<PartETag> | 包含了每个已上传的分片的ETag和PartNUmber等信息 | 否 |
UploadId | string | 通过CreateMultipartUpload操作获取的UploadId,与一个对象的分片上传对应 | 是 |
返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
BucketName | string | 执行分片上传的桶的名称 |
ETag | string | 本次上传对象后对应的Entity Tag |
Key | string | 上传文件到媒体存储服务后对应的key |
Location | string | 上传对象后对应的URI |
VersionId | string | 上传对象后相应的版本id |
列举分片上传任务
功能说明
ListMultipartUploads操作可以列出一个桶中正在进行的分片上传任务,这些分片上传任务的请求已经发起,但是还没完成或者被中止。
代码示例
using System;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
namespace DotNetSDK.ObjectOperation
{
public class ListMultipartUploadsExample
{
public static async Task ListMultipartUploads()
{
var accessKey = "<your-access-key>";
var secretKey = "<your-secret-access-key>";
var endpoint = "<your-endpoint>";
var bucketName = "<your-bucket-name>";
var credentials = new BasicAWSCredentials(accessKey, secretKey);
try
{
var conf = new AmazonS3Config
{
ServiceURL = endpoint
};
var s3Client = new AmazonS3Client(credentials, conf);
var listMultipartUploadsRequest = new ListMultipartUploadsRequest()
{
BucketName = bucketName
};
var result = await s3Client.ListMultipartUploadsAsync(listMultipartUploadsRequest);
if (result.HttpStatusCode != System.Net.HttpStatusCode.OK)
{
Console.WriteLine("fail to list multipart uploads in bucket {0}, HttpStatusCode:{1}, ErrorCode:{2}.", bucketName, (int) result.HttpStatusCode, result.HttpStatusCode);
return;
}
foreach (var multipartUpload in result.MultipartUploads)
{
Console.WriteLine("key: {0}, uploadId: {1}", multipartUpload.Key, multipartUpload.UploadId);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
请求参数
ListMultipartUploads可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
BucketName | string | 执行本操作的桶名称 | 是 |
Delimiter | string | 与Prefix参数一起用于对对象key进行分组的字符。所有key包含指定的Prefix且第一次出现Delimiter字符之间的对象作为一组。如果没有指定Prefix参数,按Delimiter对所有对象key进行分割,多个对象分割后从对象key开始到第一个Delimiter之间相同的部分形成一组 | 否 |
KeyMarker | string | 和UploadIdMarker参数一起用于指定返回哪部分分片上传的信息。如果没有设置UploadIdMarker参数,则只返回对象key按照字典顺序排序后位于KeyMarker标识符之后的分片信息。如果设置了UploadIdMarker参数,则会返回对象key等于KeyMarker且UploadId大于UploadIdMarker的分片信息 | 否 |
MaxUploads | int64 | 用于指定相应消息体中正在进行的分片上传任务的最大数量,最小值为1,默认值和最大值都是1000 | 否 |
Prefix | string | 与Delimiter参数一起用于对对象key进行分组的字符。所有key包含指定的Prefix且第一次出现Delimiter字符之间的对象作为一组 | 否 |
UploadIdMarker | string | 和KeyMarker参数一起用于指定返回哪部分分片上传的信息,仅当设置了KeyMarker参数的时候有效。设置后返回对象key等于KeyMarker且UploadId大于UploadIdMarker的分片信息 | 否 |
返回结果
ListMultipartUploads返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
BucketName | string | 执行本操作的桶名称 |
CommonPrefixes | List<string> | 当请求中设置了Delimiter和Prefix属性时,所有包含指定的Prefix且第一次出现Delimiter字符的对象key作为一组 |
Delimiter | string | 与请求中设置的Delimiter一致 |
IsTruncated | bool | 当为false时表示返回结果中包含了全部符合本次请求查询条件的分片上传任务信息,否则只返回了数量为MaxUploads个的任务信息 |
KeyMarker | string | 返回分片上传任务列表中的起始对象的key |
MaxUploads | int | 本次返回结果中包含的分片上传任务数量的最大值 |
NextKeyMarker | string | 当IsTruncated为true时,NextKeyMarker可以作为后续查询已初始化的分片上传任务请求中的KeyMarker的值 |
NextUploadIdMarker | string | 当IsTruncated为true时,NextKeyMarker可以作为后续查询已初始化的分片上传任务请求中的UploadIdMarker的值 |
Prefix | string | 限定返回分片中对应对象的key必须以Prefix作为前缀 |
UploadIdMarker | string | 返回分片上传任务列表中的起始UploadId |
MultipartUploads | List<MultipartUpload> | 包含了零个或多个已初始化的分片上传任务信息的数组。数组中的每一项包含了分片上传初始化时间、分片上传操作发起者、对象key、对象所有者、存储类型和UploadId等信息 |
列举已上传的分片
功能说明
ListParts操作可以列出一个分片上传操作中已经上传完毕但是还未合并的分片信息。使用ListParts操作需要提供object key和upload id,返回的结果最多包含1000个已上传的分片信息,默认返回1000个,可以通过设置MaxParts参数的值指定返回结果中分片信息的数量。
代码示例
using System;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
namespace DotNetSDK.ObjectOperation
{
public class ListPartsExample
{
public static async Task ListParts()
{
var accessKey = "<your-access-key>";
var secretKey = "<your-secret-access-key>";
var endpoint = "<your-endpoint>";
var bucketName = "<your-bucket-name>";
var key = "<your-object-key>";
var uploadId = "<your-upload-id>";
var credentials = new BasicAWSCredentials(accessKey, secretKey);
try
{
var conf = new AmazonS3Config
{
ServiceURL = endpoint
};
var s3Client = new AmazonS3Client(credentials, conf);
var listPartsRequest = new ListPartsRequest()
{
BucketName = bucketName,
Key = key,
UploadId = uploadId
};
var result = await s3Client.ListPartsAsync(listPartsRequest);
if (result.HttpStatusCode != System.Net.HttpStatusCode.OK)
{
Console.WriteLine("fail to list part of uploadId {0}, HttpStatusCode:{1}, ErrorCode:{2}.", uploadId, (int) result.HttpStatusCode, result.HttpStatusCode);
return;
}
Console.WriteLine("uploaded parts:");
foreach (var partDetail in result.Parts)
{
Console.WriteLine("Etag:{0}, PartNumber:{1}, Size:{2}.", partDetail.ETag, partDetail.PartNumber, partDetail.Size);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
请求参数
ListParts可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
BucketName | string | 执行本操作的桶名称 | 是 |
Key | string | 分片上传的对象的key | 是 |
MaxParts | int | 指定返回分片信息的数量,默认值和最大值均为1000 | 否 |
PartNumberMarker | string | 用于指定返回part number大于PartNumberMarker的分片信息 | 否 |
UploadId | string | 指定返回该id所属的分片上传的分片信息 | 是 |
返回结果
ListParts返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
BucketName | string | 执行本操作的桶名称 |
IsTruncated | bool | 当为false时表示返回结果中包含了全部符合本次请求查询条件的上传分片信息,否则只返回了数量为MaxParts个的分片信息 |
Key | string | 分片上传对象的名称 |
MaxParts | int | 本次返回结果中包含的上传分片数量的最大值 |
NextPartNumberMarker | int | 当IsTruncated为true时,NextPartNumberMarker可以作为后续查询已上传分片请求中的PartNumberMarker的值 |
Owner | Owner | 分片上传对象的所有者信息,包含了用户名和Id等信息 |
Parts | List<PartDetail> | 包含了已上传分片信息的数组,数组中的每一项包含了该分片的Entity tag、最后修改时间、PartNumber和大小等信息 |
UploadId | string | 分片上传操作的id |
复制分片
功能说明
CopyPart操作可以从一个已存在的对象中拷贝指定分片的数据,当拷贝的对象大小超过5GB,必须使用UploadPartCopy操作完成对象的复制。除了最后一个分片外,每个拷贝分片的大小范围是[5MB,5GB]。在一个在拷贝大对象之前,需要使用CompleteMultiPartUpload操作获取一个upload id,在完成拷贝操作之后,需要使用CompleteMultipartUpload操作组装已拷贝的分片成为一个对象。
代码示例
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
namespace DotNetSDK.ObjectOperation
{
public class CopyPartsExample
{
public static async Task CopyParts()
{
var accessKey = "<your-access-key>";
var secretKey = "<your-secret-access-key>";
var endpoint = "<your-endpoint>";
var sourceBucket = "<source-bucket>";
var sourceKey = "<source-key>";
var destinationBucket = "<destination-bucket>";
var destinationKey = "<destination-key>";
try
{
var credentials = new BasicAWSCredentials(accessKey, secretKey);
List<CopyPartResponse> copyResponses = new List<CopyPartResponse>();
var conf = new AmazonS3Config
{
ServiceURL = endpoint
};
var s3Client = new AmazonS3Client(credentials, conf);
// 发起一个分片上传操作请求,获取upload id
Task<InitiateMultipartUploadResponse> taskInitiateMultipartUploadResp = s3Client.InitiateMultipartUploadAsync(new InitiateMultipartUploadRequest()
{
BucketName = destinationBucket,
Key = destinationKey
});
var uploadId = taskInitiateMultipartUploadResp.Result.UploadId;
Console.WriteLine("upload id: {0}", uploadId);
// 获取被拷贝对象的大小
GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest
{
BucketName = sourceBucket,
Key = sourceKey
};
var getObjectMetadataResponse = await s3Client.GetObjectMetadataAsync(getObjectMetadataRequest);
long objectSize = getObjectMetadataResponse.ContentLength;
// 拷贝分片
long partSize = 5 * (long) Math.Pow(2, 20); // 5 MB.
long bytePosition = 0;
for (int i = 1; bytePosition < objectSize; i++)
{
CopyPartRequest copyPartRequest = new CopyPartRequest
{
DestinationBucket = destinationBucket,
DestinationKey = destinationKey,
SourceBucket = sourceBucket,
SourceKey = sourceKey,
UploadId = uploadId,
FirstByte = bytePosition,
LastByte = bytePosition + partSize - 1 >= objectSize ? objectSize - 1 : bytePosition + partSize - 1,
PartNumber = i
};
var copyPartResponse = await s3Client.CopyPartAsync(copyPartRequest);
copyResponses.Add(copyPartResponse);
bytePosition += partSize;
}
// 完成拷贝分片
CompleteMultipartUploadRequest completeRequest =
new CompleteMultipartUploadRequest
{
BucketName = destinationBucket,
Key = destinationKey,
UploadId = uploadId
};
completeRequest.AddPartETags(copyResponses);
CompleteMultipartUploadResponse completeUploadResponse = await s3Client.CompleteMultipartUploadAsync(completeRequest);
if (completeUploadResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
{
Console.WriteLine("fail to get copy parts, HttpStatusCode:{0}, ErrorCode:{1}.", (int) completeUploadResponse.HttpStatusCode, completeUploadResponse.HttpStatusCode);
return;
}
Console.WriteLine("copy object from {0}/{1} to {2}/{3}.", sourceBucket, sourceKey, destinationBucket, destinationKey);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
请求参数
CopyPart可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
DestinationBucket | string | 放置拷贝生成对象的桶名称 | 是 |
DestinationKey | string | 拷贝生成对象的key | 是 |
SourceBucket | string | 放置被拷贝对象的桶名称 | 是 |
SourceKey | string | 被拷贝对象的key | 是 |
UploadId | string | 与本次拷贝操作相应的分片上传Id | 是 |
SourceVersionId | string | 指定被拷贝对象的版本信息,如果不指定,默认拷贝对象的当前版本 | 否 |
返回结果
CopyPart返回的结果如下:
参数 | 类型 | 说明 |
---|---|---|
ContentLength | long | 拷贝分片的长度 |
ETag | string | 拷贝分片的ETag |
LastModified | string | 拷贝分片的最新修改时间 |
PartNumber | int | 拷贝分片的序号 |
取消分片上传任务
功能说明
AbortMultipartUpload操作用于终止一个分片上传任务。当一个分片上传任务被中止后,不会再有数据通过与之相应的upload id上传,同时已经被上传的分片所占用的空间会被释放。执行AbortMultipartUpload操作后,正在上传的分片可能会上传成功也可能会被中止,所以必要的情况下需要执行多次AbortMultipartUpload操作去释放全部上传成功的分片所占用的空间。可以通过执行ListParts操作来确认所有中止分片上传后所有已上传分片的空间是否被被释放。
代码示例
using System;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
namespace DotNetSDK.ObjectOperation
{
public class AbortMultipartUploadExample
{
public static async Task AbortMultipartUpload()
{
var accessKey = "<your-access-key>";
var secretKey = "<your-secret-access-key>";
var endpoint = "<your-endpoint>";
var bucketName = "<your-bucket-name>";
var key = "<your-object-key>";
var uploadId = "<your-upload-id>";
try
{
var credentials = new BasicAWSCredentials(accessKey, secretKey);
var conf = new AmazonS3Config
{
ServiceURL = endpoint
};
var s3Client = new AmazonS3Client(credentials, conf);
var abortMultipartUploadRequest = new AbortMultipartUploadRequest()
{
BucketName = bucketName,
Key = key,
UploadId = uploadId
};
var result = await s3Client.AbortMultipartUploadAsync(abortMultipartUploadRequest);
if (result.HttpStatusCode != System.Net.HttpStatusCode.NoContent)
{
Console.WriteLine("fail to abort multipart upload, uploadId:{0}, HttpStatusCode:{1}, ErrorCode:{2}.", uploadId, (int) result.HttpStatusCode, result.HttpStatusCode);
return;
}
Console.WriteLine("aborted multipart upload, uploadId:{0}.", uploadId);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
请求参数
AbortMultipartUpload可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
BucketName | string | 桶的名称 | 是 |
Key | string | 分片上传的对象的key | 是 |
UploadId | string | 指定需要终止的分片上传的id | 是 |