简介
本文介绍对象存储 COS 通过 iOS SDK 实现上传对象功能的示例代码和描述。包括高级接口、简单接口、分块上传三个部分。
注意事项
若您使用简单上传,需要具有目标对象的写权限:在您进行 授权策略 时,action 需要设置为
cos:PutObject
,更多授权请参见 支持CAM的业务接口。若您使用高级接口的自动分块上传或使用简单接口实现分块上传,需要具有目标对象的初始化分块上传、上传分块、完成分块上传的权限:在您进行 授权策略 时,action 需要设置为
cos:InitiateMultipartUpload
,cos:UploadPart
,cos:CompleteMultipartUpload
,更多授权请参见 支持CAM的业务接口。若您使用高级接口的断点续传,需要具有目标对象的初始化分块上传、上传分块、完成分块上传、列举分块上传任务、列举已上传分块的权限:在您进行 授权策略 时,action 需要设置为
cos:InitiateMultipartUpload
,cos:UploadPart
,cos:CompleteMultipartUpload
,cos:ListMultipartUploads
,cos:ListParts
更多授权请参见 支持CAM的业务接口。使用预签名URL上传时,最大支持上传 5GB 文件。
相关示例
功能名称 | 描述 | 示例代码 |
高级接口 | 高级接口封装了简单上传、分块上传接口,根据文件大小智能的选择上传方式,同时支持续传功能。 | |
简单操作 | PUT Object 接口可以上传一个对象至指定存储桶中,该操作需要请求者对存储桶有 WRITE 权限。最大支持上传不超过5GB的对象,5GB以上对象请使用 分块上传 或 高级接口 上传。 | |
分块操作 | 分块上传可以实现将整个对象切分为多个分块,然后再将这些分块上传到对象存储(Cloud Object Storage,COS)。 |
高级接口
注意:
分块阈值用来区分使用简单上传还是分块上传,阈值支持用户自行配置,默认为1MB。
分块大小支持用户自行配置,默认为1MB。
对流NSData类型文件的上传,统一使用简单上传。
对文件类型的上传,小于分块阈值的文件,高级接口会选择简单上传,大于分块阈值的文件,高级接口会选择分块上传。
功能说明
高级接口封装了简单上传、分块上传接口,根据文件大小智能的选择上传方式,同时支持续传功能。
使用案例:上传本地文件
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];/** 本地文件路径,请确保 URL 是以 file:// 开头,格式如下 :1. [NSURL URLWithString:@"file:////var/mobile/Containers/Data/Application/DBPF7490-D5U8-4ABF-A0AF-CC49D6A60AEB/Documents/exampleobject"]2. [NSURL fileURLWithPath:@"/var/mobile/Containers/Data/Application/DBPF7490-D5U8-4ABF-A0AF-CC49D6A60AEB/Documents/exampleobject"]*/NSURL* url = [NSURL fileURLWithPath:@"文件的URL"];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = @"exampleobject";// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = url;// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * fileUrl = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[put setInitMultipleUploadFinishBlock:^(QCloudInitiateMultipartUploadResult *multipleUploadInitResult,QCloudCOSXMLUploadObjectResumeData resumeData) {// 在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData,uploadidNSString* uploadId = multipleUploadInitResult.uploadId;}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
说明:
let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject";// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = NSURL.fileURL(withPath: "Local File Path") as AnyObject;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};// 设置上传参数put.initMultipleUploadFinishBlock = {(multipleUploadInitResult, resumeData) in// 在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData,以及 uploadIdif let multipleUploadInitResult = multipleUploadInitResult {let uploadId = multipleUploadInitResult.uploadId}}QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
说明:
使用案例:上传二进制数据
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = @"exampleobject";// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = [@"My Example Content" dataUsingEncoding:NSUTF8StringEncoding];// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 新增字节数// totalBytesSent 本次上传的总字节数// totalBytesExpectedToSend 本地上传的目标字节数}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * fileUrl = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
说明:
let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject";// 需要上传的对象内容let dataBody:NSData = "wrwrwrwrwrw".data(using: .utf8)! as NSData;put.body = dataBody;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 新增字节数// totalBytesSent 本次上传的总字节数// totalBytesExpectedToSend 本地上传的目标字节数};QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
说明:
使用案例:上传暂停、继续与取消
对于上传任务,可以通过以下方式暂停:
NSError *error;NSData *resmeData = [put cancelByProductingResumeData:&error];
暂停之后,可以通过以下方式续传:
QCloudCOSXMLUploadObjectRequest *resumeRequest = [QCloudCOSXMLUploadObjectRequest requestWithRequestData:resmeData];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:resumeRequest];
也通过以下方式取消上传:
//丢弃该上传[put abort:^(id outputObject, NSError *error) {}];
对于上传任务,可以通过以下方式暂停:
var error : NSError?;var uploadResumeData:Data = put.cancel(byProductingResumeData:&error) as Data;
暂停之后,可以通过以下方式续传:
var resumeRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>.init(request: uploadResumeData);QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(resumeRequest);
也通过以下方式取消上传:
//丢弃该上传put.abort { (outputObject, error) in}
使用案例:批量上传
for (int i = 0; i<20; i++) {QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = [NSString stringWithFormat:@"exampleobject-%d",i];// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = [@"My Example Content" dataUsingEncoding:NSUTF8StringEncoding];// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * fileUrl = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];}
for i in 1...10 {let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject-".appendingFormat("%d", i);// 需要上传的对象内容let dataBody:NSData = "wrwrwrwrwrw".data(using: .utf8)! as NSData;put.body = dataBody;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件的下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);}
使用案例:自定义简单上传与分块上传的阈值
for (int i = 0; i<20; i++) {QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = [NSString stringWithFormat:@"exampleobject-%d",i];// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = [@"My Example Content" dataUsingEncoding:NSUTF8StringEncoding];// 自定义简单上传与分块上传的阈值:默认当文件大于1MB时启用分块上传put.mutilThreshold = 10*1024*1024;// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * location = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];}
for i in 1...10 {let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject".appendingFormat("%d", i);// 需要上传的对象内容let dataBody:NSData = "wrwrwrwrwrw".data(using: .utf8)! as NSData;put.body = dataBody;// 自定义简单上传与分块上传的阈值:默认当文件大于1MB时启用分块上传put.mutilThreshold = 10*1024*1024;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);}
使用案例:自定义分块大小
for (int i = 0; i<20; i++) {QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = [NSString stringWithFormat:@"exampleobject-%d",i];// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = [@"My Example Content" dataUsingEncoding:NSUTF8StringEncoding];// 自定义分片大小,默认为1MBput.sliceSize = 10*1024*1024;// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * location = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];}
for i in 1...10 {let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject-".appendingFormat("%d", i);// 需要上传的对象内容let dataBody:NSData = "wrwrwrwrwrw".data(using: .utf8)! as NSData;put.body = dataBody;// 自定义分片大小,默认为1MBput.sliceSize = 10*1024*1024// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);}
使用案例:上传时限速
注意:
需要 COS iOS SDK v5.8.0 及以上版本。
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = @"exampleobject";// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量put.body = [@"My Example Content" dataUsingEncoding:NSUTF8StringEncoding];// 使用trafficLimit参数设置上传限速,单位为bit/s,限速值设置范围为819200 - 838860800,即800Kb/s - 800Mb/s。put.trafficLimit = 819200;// 监听上传进度[put setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)}];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * location = result.location;// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "exampleobject"// 需要上传的对象内容let dataBody:NSData = "wrwrwrwrwrw".data(using: .utf8)! as NSData;put.body = dataBody;// 使用trafficLimit参数设置上传限速,单位为bit/s,限速值设置范围为819200 - 838860800,即800Kb/s - 800Mb/s。put.trafficLimit = 819200;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件的 etaglet eTag = result.eTag// 文件下载链接let location = result.location;// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}// 监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent,totalBytesExpectedToSend) in// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)// totalBytesSent 已发送的字节数// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
使用案例:创建目录
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 要创建的目录的名称put.object = @"dir1";// 需要上传的对象内容,如需创建目录使用空串生成NSData即可put.body = [@"" dataUsingEncoding:NSUTF8StringEncoding];// 监听上传结果[put setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {// 在上传结果 result.location 中获取上传文件的下载链接NSString * location = result.location;}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
说明:
let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = "dir/";// 需要上传的对象内容let dataBody:NSData = "".data(using: .utf8)! as NSData;put.body = dataBody;// 监听上传结果put.setFinish { (result, error) in// 获取上传结果if let result = result {// 文件下载链接let location = result.location;} else {print(error!);}}QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
说明:
简单操作
功能说明
注意:
Key(文件名)不能以
/
结尾,否则会被识别为文件夹。使用案例:简单上传对象
QCloudPutObjectRequest* put = [QCloudPutObjectRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = @"exampleobject";// 文件内容,可以传入NSData*或者NSURL*类型的变量put.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];[put setFinishBlock:^(id result, NSError *error) {// result 包含响应的 header 信息// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSXMLService defaultCOSXML] PutObject:put];
说明:
let putObject = QCloudPutObjectRequest<AnyObject>.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketputObject.bucket = "examplebucket-1250000000";// 需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量let dataBody:NSData? = "wrwrwrwrwrw".data(using: .utf8) as NSData?;putObject.body = dataBody!;// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"putObject.object = "exampleobject";putObject.finishBlock = {(result,error) inif let result = result {// 获取文件crc64let crc64 = (result as? NSObject)?.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}QCloudCOSXMLService.defaultCOSXML().putObject(putObject);
说明:
分块操作
分块上传流程介绍
分块上传的流程
1. 初始化分块上传(Initiate Multipart Upload),得到 UploadId。
2. 使用 UploadId 上传分块(Upload Part)。
3. 完成分块上传(Complete Multipart Upload)。
分块继续上传的流程
1. 如果没有记录 UploadId,查询分块上传任务(List Multipart Uploads),得到对应文件的 UploadId。
2. 使用 UploadId 列出已上传的分块(List Parts)。
3. 使用 UploadId 上传剩余的分块(Upload Part)。
4. 完成分块上传(Complete Multipart Upload)。
![](https://qcloudimg.tencent-cloud.cn/image/document/86b8fa95556e1a21e9385d0fa316a05d.png)
![](https://qcloudimg.tencent-cloud.cn/image/document/86b8fa95556e1a21e9385d0fa316a05d.png)
注意:
除了最后一块 Part,其他 Part 的大小不能小于1MB,否则会导致调用 Complete Multipart Upload 接口失败。
要上传的文件切分成 Part 之后,文件顺序是通过上传过程中指定的 partNumber 来确定的,实际执行中并没有顺序要求,因此可以实现并发上传。
具体的并发个数并不是越多速度越快,要结合用户自身的网络情况和设备负载综合考虑。网络情况较好时,建议增大分片大小。反之,减小分片大小。
默认情况下,已经上传但还没有调用 CompleteMultipartUpload 的 Part 是不会被自动回收的,并且会占用存储空间进而产生存储费用。因此如果要终止上传并删除占用的空间请调用 AbortMultipartUpload。
使用案例:分块上传完整示例代码
NSString * object = @"test.png";NSString * bucket = @"bucket";NSString * regionName = @"regionName";NSString * filePath = @"本地文件路径";// 1.初始化分块上传QCloudInitiateMultipartUploadRequest *uploadRequet = [QCloudInitiateMultipartUploadRequest new];uploadRequet.bucket = bucket;uploadRequet.regionName = regionName;uploadRequet.object = object;dispatch_semaphore_t semp = dispatch_semaphore_create(0);__block QCloudInitiateMultipartUploadResult * initResult;[uploadRequet setFinishBlock:^(QCloudInitiateMultipartUploadResult *_Nonnull result, NSError *_Nonnull error) {initResult = result;if (error) {NSLog(@"初始化失败:%@",error);}else{NSLog(@"初始化成功:%@",result);}dispatch_semaphore_signal(semp);}];[[QCloudCOSXMLService defaultCOSXML] InitiateMultipartUpload:uploadRequet];dispatch_semaphore_wait(semp, DISPATCH_TIME_FOREVER);// 2.整理需要上传的分块。NSMutableArray *allParts = [NSMutableArray new];NSURL *url = [NSURL URLWithString:filePath];NSInteger dataContentLength = QCloudFileSize(url.relativePath);int64_t offset = 0;int64_t restContentLength = dataContentLength;for (int i = 0;; i++) {int64_t slice = 1024 * 1024;if (restContentLength < 1024 * 1024) {slice = restContentLength;}QCloudFileOffsetBody *body = [[QCloudFileOffsetBody alloc] initWithFile:url offset:offset slice:slice];[allParts addObject:body];offset += slice;body.index = i;restContentLength -= slice;if (restContentLength <= 0) {break;}}// 3.开始上传所有分块NSMutableArray * partInfos = [NSMutableArray new];for (int i = 0; i < allParts.count; i++) {__block QCloudFileOffsetBody *body = allParts[i];QCloudUploadPartRequest *request = [QCloudUploadPartRequest new];dispatch_semaphore_t semppart = dispatch_semaphore_create(0);request.bucket = bucket;request.regionName = regionName;request.object = object;request.partNumber = (int)body.index + 1;request.uploadId = initResult.uploadId;request.body = body;[request setFinishBlock:^(QCloudUploadPartResult *outputObject, NSError *error) {if (error) {NSLog(@"第%ld个分块上传失败:%@",(int)body.index + 1,error);}else{QCloudMultipartInfo * item = [QCloudMultipartInfo new];item.partNumber = @(request.partNumber).stringValue;item.eTag = outputObject.eTag;[partInfos addObject:item];NSLog(@"第%ld个分块上传成功:%@",(int)body.index + 1,outputObject);}dispatch_semaphore_signal(semppart);}];[[QCloudCOSXMLService defaultCOSXML] UploadPart:request];dispatch_semaphore_wait(semppart, DISPATCH_TIME_FOREVER);}// 4.确认分块上传。QCloudCompleteMultipartUploadRequest *complete = [QCloudCompleteMultipartUploadRequest new];complete.object = object;complete.bucket = bucket;complete.uploadId = initResult.uploadId;complete.regionName = regionName;QCloudCompleteMultipartUploadInfo *info = [QCloudCompleteMultipartUploadInfo new];[partInfos sortUsingComparator:^NSComparisonResult(QCloudMultipartInfo *_Nonnull obj1, QCloudMultipartInfo *_Nonnull obj2) {int a = obj1.partNumber.intValue;int b = obj2.partNumber.intValue;if (a < b) {return NSOrderedAscending;} else {return NSOrderedDescending;}}];info.parts = partInfos;complete.parts = info;[complete setFinishBlock:^(QCloudUploadObjectResult *outputObject, NSError *error) {if (error) {NSLog(@"分块上传确认失败:%@",error);[expectation fulfill];}else{NSLog(@"分块上传确认成功:%@",outputObject);}}];[[QCloudCOSXMLService defaultCOSXML] CompleteMultipartUpload:complete];
let object = "test.png"let bucket = "bucket"let regionName = "regionName"let filePath = "本地文件路径"// 1.初始化分块上传let uploadRequest = QCloudInitiateMultipartUploadRequest()uploadRequest.bucket = bucketuploadRequest.regionName = regionNameuploadRequest.object = objectlet semp = DispatchSemaphore(value: 0)var initResult: QCloudInitiateMultipartUploadResult?uploadRequest.setFinish { (result, error) ininitResult = resultif let error = error {print("初始化失败:\\(error)")} else {print("初始化成功:\\(String(describing: result))")}semp.signal()}QCloudCOSXMLService.defaultCOSXML().initiateMultipartUpload(uploadRequest)_ = semp.wait(timeout: .distantFuture)// 2.整理需要上传的分块。var allParts = NSMutableArray();let url = URL(fileURLWithPath: filePath)let dataContentLength = QCloudFileSize(url.relativePath)var offset: Int64 = 0var restContentLength = dataContentLengthfor i in 0... {var slice: Int64 = 1024 * 1024if restContentLength < 1024 * 1024 {slice = Int64(restContentLength)}let body = QCloudFileOffsetBody(file: url, offset: UInt(offset), slice: UInt(slice))allParts.add(body!)offset += slicebody?.index = UInt(i)restContentLength -= UInt64(slice)if restContentLength <= 0 {break}}// 3.开始上传所有分块var partInfos = NSMutableArray()for i in 0..<allParts.count {var body:QCloudFileOffsetBody = allParts[i] as! QCloudFileOffsetBodylet request = QCloudUploadPartRequest<QCloudFileOffsetBody>()let semppart = DispatchSemaphore(value: 0)request.bucket = bucketrequest.regionName = regionNamerequest.object = objectrequest.partNumber = Int32(Int(body.index) + 1)request.uploadId = initResult!.uploadIdrequest.body = bodyrequest.setFinish { (outputObject, error) inif let error = error {print("第\\(Int(body.index) + 1)个分块上传失败:\\(error)")} else {let item = QCloudMultipartInfo()item.partNumber = "\\(request.partNumber)"item.eTag = outputObject!.eTagpartInfos.add(item)print("第\\(Int(body.index) + 1)个分块上传成功:\\(String(describing: outputObject))")}semppart.signal()}QCloudCOSXMLService.defaultCOSXML().uploadPart(request as! QCloudUploadPartRequest<AnyObject>)_ = semppart.wait(timeout: .distantFuture)}// 4.确认分块上传。let complete = QCloudCompleteMultipartUploadRequest()complete.object = objectcomplete.bucket = bucketcomplete.uploadId = initResult!.uploadIdcomplete.regionName = regionNamelet info = QCloudCompleteMultipartUploadInfo()var swiftInfos = partInfos as! [QCloudMultipartInfo];swiftInfos.sort { obj1, obj2 inreturn obj1.partNumber < obj2.partNumber}info.parts = swiftInfoscomplete.parts = infocomplete.setFinish { (outputObject, error) inif let error = error {print("分块上传确认失败:\\(error)")} else {print("分块上传确认成功:\\(String(describing: outputObject))")}}QCloudCOSXMLService.defaultCOSXML().completeMultipartUpload(complete)
使用案例:查询分块上传
功能说明
查询指定存储桶中正在进行的分块上传(List Multipart Uploads)。
示例代码
QCloudListBucketMultipartUploadsRequest* uploads = [QCloudListBucketMultipartUploadsRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketuploads.bucket = @"examplebucket-1250000000";// 设置最大返回的 multipart 数量,合法取值从 1 到 1000uploads.maxUploads = 100;[uploads setFinishBlock:^(QCloudListMultipartUploadsResult* result,NSError *error) {// 可以从 result 中返回分块信息// 进行中的分块上传对象NSArray<QCloudListMultipartUploadContent*> *uploads = result.uploads;}];[[QCloudCOSXMLService defaultCOSXML] ListBucketMultipartUploads:uploads];
let listParts = QCloudListBucketMultipartUploadsRequest.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketlistParts.bucket = "examplebucket-1250000000";// 设置最大返回的 multipart 数量,合法取值从 1 到 1000listParts.maxUploads = 100;listParts.setFinish { (result, error) inif let result = result {// 未完成的所有分块上传任务let uploads = result.uploads;} else {print(error!);}}QCloudCOSXMLService.defaultCOSXML().listBucketMultipartUploads(listParts);
使用案例:初始化分块上传
功能说明
初始化 Multipart Upload 上传操作,获取对应的 uploadId(Initiate Multipart Upload)。
示例代码
QCloudInitiateMultipartUploadRequest* initRequest = [QCloudInitiateMultipartUploadRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketinitRequest.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"initRequest.object = @"exampleobject";// 将作为对象的元数据返回initRequest.cacheControl = @"cacheControl";initRequest.contentDisposition = @"contentDisposition";// 定义 Object 的 ACL 属性。有效值:private,public-read-write,public-read;默认值:privateinitRequest.accessControlList = @"public";// 赋予被授权者读的权限。initRequest.grantRead = @"grantRead";// 赋予被授权者全部权限initRequest.grantFullControl = @"grantFullControl";[initRequest setFinishBlock:^(QCloudInitiateMultipartUploadResult* outputObject,NSError *error) {// 获取分块上传的 uploadId,后续的上传都需要这个 ID,请保存以备后续使用self->uploadId = outputObject.uploadId;}];[[QCloudCOSXMLService defaultCOSXML] InitiateMultipartUpload:initRequest];
let initRequest = QCloudInitiateMultipartUploadRequest.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketinitRequest.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"initRequest.object = "exampleobject";initRequest.setFinish { (result, error) inif let result = result {// 获取分块上传的 uploadId,后续的上传都需要这个 ID,请保存以备后续使用self.uploadId = result.uploadId;} else {print(error!);}}QCloudCOSXMLService.defaultCOSXML().initiateMultipartUpload(initRequest);
使用案例:上传分块
功能说明
分块上传对象(Upload Part)。
示例代码
QCloudUploadPartRequest* request = [QCloudUploadPartRequest new];// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketrequest.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"request.object = @"exampleobject";// 块编号request.partNumber = 1;// 标识本次分块上传的 ID;使用 Initiate Multipart Upload 接口初始化分块上传时会得到一个 uploadIdrequest.uploadId = uploadId;// 上传的数据:支持 NSData*,NSURL(本地 URL) 和 QCloudFileOffsetBody * 三种类型request.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];[request setSendProcessBlock:^(int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend) {// 上传进度信息// bytesSent 新增字节数// totalBytesSent 本次上传的总字节数// totalBytesExpectedToSend 本地上传的目标字节数}];[request setFinishBlock:^(QCloudUploadPartResult* outputObject, NSError *error) {QCloudMultipartInfo *part = [QCloudMultipartInfo new];// 获取所上传分块的 etagpart.eTag = outputObject.eTag;part.partNumber = @"1";// 保存起来用于最好完成上传时使用self.parts = @[part];// 获取文件crc64NSString * crc64 = [[outputObject __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSXMLService defaultCOSXML] UploadPart:request];
let uploadPart = QCloudUploadPartRequest<AnyObject>.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketuploadPart.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"uploadPart.object = "exampleobject";uploadPart.partNumber = 1;// 标识本次分块上传的 IDif let uploadId = self.uploadId {uploadPart.uploadId = uploadId;}// 示例文件内容let dataBody:NSData? = "wrwrwrwrwrwwrwrwrwrwrwwwrwrw".data(using: .utf8) as NSData?;uploadPart.body = dataBody!;uploadPart.setFinish { (result, error) inif let result = result {let mutipartInfo = QCloudMultipartInfo.init();// 获取分块的 etagmutipartInfo.eTag = result.eTag;mutipartInfo.partNumber = "1";// 保存起来用于最后完成上传时使用self.parts = [mutipartInfo];// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}uploadPart.sendProcessBlock = {(bytesSent,totalBytesSent,totalBytesExpectedToSend) in// 上传进度信息// bytesSent 新增字节数// totalBytesSent 本次上传的总字节数// totalBytesExpectedToSend 本地上传的目标字节数}QCloudCOSXMLService.defaultCOSXML().uploadPart(uploadPart);
使用案例:查询已上传的分块
功能说明
查询特定分块上传操作中的已上传的块(List Parts)。
示例代码
QCloudListMultipartRequest* request = [QCloudListMultipartRequest new];// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"request.object = @"exampleobject";// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketrequest.bucket = @"examplebucket-1250000000";// 在初始化分块上传的响应中,会返回一个唯一的描述符(upload ID)request.uploadId = uploadId;[request setFinishBlock:^(QCloudListPartsResult * _Nonnull result,NSError * _Nonnull error) {// 从 result 中获取已上传分块信息// 用来表示每一个块的信息NSArray<QCloudMultipartUploadPart*> *parts = result.parts;}];[[QCloudCOSXMLService defaultCOSXML] ListMultipart:request];
let req = QCloudListMultipartRequest.init();// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"req.object = "exampleobject";// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketreq.bucket = "examplebucket-1250000000";// 在初始化分块上传的响应中,会返回一个唯一的描述符(upload ID)if let uploadId = self.uploadId {req.uploadId = uploadId;}req.setFinish { (result, error) inif let result = result {// 所有已完成的分片let parts = result.parts} else {print(error!);}}QCloudCOSXMLService.defaultCOSXML().listMultipart(req);
使用案例:完成分块上传
功能说明
完成整个文件的分块上传(Complete Multipart Upload)。
示例代码
QCloudCompleteMultipartUploadRequest *completeRequst = [QCloudCompleteMultipartUploadRequest new];// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"completeRequst.object = @"exampleobject";// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketcompleteRequst.bucket = @"examplebucket-1250000000";// 本次要查询的分块上传的 uploadId,可从初始化分块上传的请求结果 QCloudInitiateMultipartUploadResult 中得到completeRequst.uploadId = uploadId;// 已上传分块的信息QCloudCompleteMultipartUploadInfo *partInfo = [QCloudCompleteMultipartUploadInfo new];NSMutableArray * parts = [self.parts mutableCopy];// 对已上传的块进行排序[parts sortUsingComparator:^NSComparisonResult(QCloudMultipartInfo* _Nonnull obj1,QCloudMultipartInfo* _Nonnull obj2) {int a = obj1.partNumber.intValue;int b = obj2.partNumber.intValue;if (a < b) {return NSOrderedAscending;} else {return NSOrderedDescending;}}];partInfo.parts = [parts copy];completeRequst.parts = partInfo;[completeRequst setFinishBlock:^(QCloudUploadObjectResult * _Nonnull result,NSError * _Nonnull error) {// 从 result 中获取上传结果// 获取文件crc64NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];}];[[QCloudCOSXMLService defaultCOSXML] CompleteMultipartUpload:completeRequst];
let complete = QCloudCompleteMultipartUploadRequest.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketcomplete.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"complete.object = "exampleobject";// 本次要查询的分块上传的 uploadId,可从初始化分块上传的请求结果// QCloudInitiateMultipartUploadResult 中得到complete.uploadId = "exampleUploadId";if let uploadId = self.uploadId {complete.uploadId = uploadId;}// 已上传分块的信息let completeInfo = QCloudCompleteMultipartUploadInfo.init();if self.parts == nil {print("没有要完成的分块");return;}if self.parts != nil {completeInfo.parts = self.parts ?? [];}complete.parts = completeInfo;complete.setFinish { (result, error) inif let result = result {// 文件的 eTaglet eTag = result.eTag// 不带签名的文件链接let location = result.location// 获取文件crc64let crc64 = result.__originHTTPURLResponse__.allHeaderFields["x-cos-hash-crc64ecma"];} else {print(error!);}}QCloudCOSXMLService.defaultCOSXML().completeMultipartUpload(complete);
使用案例:终止分块上传
功能说明
终止一个分块上传操作并删除已上传的块(Abort Multipart Upload)。
示例代码
QCloudAbortMultipfartUploadRequest *abortRequest = [QCloudAbortMultipfartUploadRequest new];// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"abortRequest.object = @"exampleobject";// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketabortRequest.bucket = @"examplebucket-1250000000";// 本次要终止的分块上传的 uploadId// 可从初始化分块上传的请求结果 QCloudInitiateMultipartUploadResult 中得到abortRequest.uploadId = @"exampleUploadId";[abortRequest setFinishBlock:^(id outputObject, NSError *error) {// 可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息NSDictionary * result = (NSDictionary *)outputObject;}];[[QCloudCOSXMLService defaultCOSXML]AbortMultipfartUpload:abortRequest];
let abort = QCloudAbortMultipfartUploadRequest.init();// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucketabort.bucket = "examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"abort.object = "exampleobject";// 本次要查询的分块上传的 uploadId,可从初始化分块上传的请求结果// QCloudInitiateMultipartUploadResult 中得到abort.uploadId = self.uploadId!;abort.finishBlock = {(result,error)inif let result = result {// 可以从 result 中获取服务器返回的 header 信息} else {print(error!)}}QCloudCOSXMLService.defaultCOSXML().abortMultipfartUpload(abort);
SDK API 参考
API 操作
关于简单操作的 API 接口说明,请参见 PUT Object 文档。
关于分块操作的 API 接口说明,请参见 List Multipart Uploads 、Initiate Multipart Upload 、Upload Part 、List Parts、Abort Multipart Upload、Complete Multipart Upload文档。