一、相关资源
·SDK 源码地址请参考:XML iOS SDK。
·SDK 快速下载地址:XML iOS SDK。
·示例 Demo 可参考:XML iOS SDK Demo。
·SDK 接口与参数文档请参见 SDK API 参考。
·SDK 文档中的所有示例代码请参见 SDK 代码示例。
·SDK 更新日志请参见:ChangeLog。
·SDK 常见问题请参见:iOS SDK 常见问题。
二、环境配置与准备
3. 你需要获取一个腾讯云 API 密钥,该密钥是你使用 COS SDK 各项功能的前提。
注意:说明:
三、方式一:使用 Cocoapods 集成(推荐)
COS SDK 有三个版本:标准版、精简版、无腾讯灯塔版。
·标准版:包含了 COS API 的所有功能,功能最为完善。
·精简版:仅包含 COS 的文件上传/下载功能(如果你仅仅使用到上传和下载功能,并且对 SDK 体积要求较高,推荐使用精简版 SDK)。
·无腾讯灯塔版:在标准版的基础上移除了腾讯的灯塔数据上报服务。
注意:说明:
注意:为了持续跟踪和优化 SDK 的质量,给你带来更好的使用体验,我们在 SDK 中引入了 腾讯灯塔 SDK,腾讯灯塔只对 COS 侧的请求性能进行监控不会上报业务侧数据。
在你工程的 Podfile 文件中添加:
标准版精简版无腾讯灯塔版pod 'QCloudCOSXML'pod 'QCloudCOSXML/Transfer'pod 'QCloudCOSXML/Slim'
注意:说明:
注意:精简版 SDK 和无腾讯灯塔版 SDK 是通过 Cocoapods 的 Subspec 功能实现的,因此目前只支持通过自动集成的方式进行引入。
注意:
四、方式二:手动集成
我们在 SDK Releases 里提供了 SDK 发布至今所有的正式包。集成方式参考如下:
1. 将 QCloudCOSXML.framework、QCloudCore.framework 、QCloudTrack.framework 和 COSBeaconAPI_Base.framework 拖入到工程中。
注意:说明:
2. 添加以下系统依赖:
·CoreTelephony
·Foundation
·SystemConfiguration
·libc++.tbd
3. 在项目 Build Setting 中设置 Other Linker Flags,添加以下参数:
-ObjC
注意:说明:
注意:SDK 提供了打包脚本,支持根据业务需求自行打包(该打包脚本依赖于 Cocoapods,请先确保你的开发环境安装了 Cocoapods)。打包步骤如下:
注意:1. 下载源码:git clone https://github.com/tencentyun/qcloud-sdk-ios。
注意:2. 运行打包脚本:source package.sh。
注意:3. 将打包产物拖到工程中,然后按照上面手动集成的方式操作即可。
注意:
五、导入头文件
Objective-CSwift标准版精简版无腾讯灯塔版#import <QCloudCOSXML/QCloudCOSXML.h>#import <QCloudCOSXML/QCloudCOSXMLTransfer.h>#import <QCloudCOSXML/QCloudCOSXML.h>标准版精简版无腾讯灯塔版import QCloudCOSXMLimport QCloudCOSXMLimport QCloudCOSXML
六、初始化 COS
注意:说明:
注意:在使用 COS SDK 之前,我们需要在控制台创建一个存储桶,创建指引请参见 控制台快速入门。
在应用启动后,初始化 COS SDK。
Objective-CSwiftSwiftUI//AppDelegate.m@interface AppDelegate()@end@implementation AppDelegate- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions { QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new]; QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] init]; // 存储桶所在地域简称可以在控制台查看:https://console.cloud.tencent.com/cos5/bucket // 例如广州地区是 ap-guangzhou,COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = @"COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; configuration.endpoint = endpoint; // 初始化 COS 服务示例 [QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration]; [QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration: configuration]; return YES;}@end//AppDelegate.swiftclass AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); // 存储桶所在地域简称可以在控制台查看:https://console.cloud.tencent.com/cos5/bucket // 例如广州地区是 ap-guangzhou,COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = "COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; config.endpoint = endpoint; // 初始化 COS 服务示例 QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger( with: config); return true }}import SwiftUIimport QCloudCOSXML@mainstruct SwiftUIDemoApp: App { init() { // 在应用初始化时调用 SDK 配置 COSManager.shared.setupCOSSDK(); } var body: some Scene { WindowGroup { ContentView() } }}class COSManager: NSObject { static let shared = COSManager() private override init() {} func setupCOSSDK() { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); // 存储桶所在地域简称可以在控制台查看:https://console.cloud.tencent.com/cos5/bucket // 例如广州地区是 ap-guangzhou,COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = "COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; config.endpoint = endpoint; // 初始化 COS 服务示例 QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: config); }}
七、设置 API 访问密钥
访问密钥是 COS SDK 访问所有服务的前提,密钥分为:永久密钥和临时密钥。SDK 内部提供了诸多方法来设置密钥,具体如下:
·临时密钥:和每一个 COS 请求关联,业务方在发起请求时进行设置,优先级高于使用回调设置密钥的方式。
·密钥回调:SDK 会在首次和缓存的密钥快过期时以回调的方式重新获取访问密钥。
注意:强烈建议用户 使用临时密钥 调用 SDK,通过临时授权的方式进一步提高 SDK 使用的安全性。申请临时密钥时,请遵循 最小权限指引原则,防止泄露目标存储桶或对象之外的资源。
临时密钥密钥回调
注意:说明:
Objective-CSwift// 以文件上传请求为例QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];QCloudCredential * credential = [QCloudCredential new];// 临时密钥 IDcredential.secretID = @"secretID"; // 临时密钥 keycredential.secretKey = @"secretKey"; // 临时密钥 tokencredential.token = @"token"; // 设置临时密钥put.credential = credential;// 本地文件路径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:^(id outputObject, NSError *error) { //可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息 NSDictionary * result = (NSDictionary *)outputObject;}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];// 以文件上传请求为例let put:QCloudCOSXMLUploadObjectRequest = QCloudCOSXMLUploadObjectRequest<AnyObject>();let credential = QCloudCredential()// 临时密钥 IDcredential.secretID = "secretID"// 临时密钥 Keycredential.secretKey = "secretKey"// 临时密钥 tokencredential.token = "token"// 设置临时密钥put.credential = credential// 存储桶名称,由 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 error != nil{ print(error!); }else{ print(result!); }}//监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) in // bytesSent 本次要发送的字节数(一个大文件可能要分多次发送) // totalBytesSent 已发送的字节数 // totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};//设置上传参数put.initMultipleUploadFinishBlock = {(multipleUploadInitResult, resumeData) in //在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData //并且可以通过 resumeData 生成一个分块上传的请求 let resumeUploadRequest = QCloudCOSXMLUploadObjectRequest<AnyObject> .init(request: resumeData as Data?);}QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);
注意:说明:
客户端管理密钥服务端签名Objective-CSwiftSwiftUI//AppDelegate.m//AppDelegate 需遵循 QCloudSignatureProvider @interface AppDelegate()<QCloudSignatureProvider>@end@implementation AppDelegate- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions { QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new]; QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] init]; endpoint.regionName = @"COS_REGION"; endpoint.useHTTPS = true; configuration.endpoint = endpoint; // 设置密钥回调代理 configuration.signatureProvider = self; [QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration]; [QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration: configuration]; return YES;}// 密钥回调的代理方法- (void)signatureWithFields:(QCloudSignatureFields*)fileds request:(QCloudBizHTTPRequest*)request urlRequest:(NSMutableURLRequest*)urlRequst compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock{ /** * 此处获取密钥,如果使用永久密钥则忽略 * … */ /** * 此处既可以是临时密钥也可以是永久密钥 * 临时密钥获取见:https://cloud.tencent.com/document/product/436/14048 * 注意:永久密钥不可用于生产环境,仅可作为调试使用 */ QCloudCredential* credential = [QCloudCredential new]; // 密钥 SecretId credential.secretID = @"SECRETID"; // 密钥 SecretKey credential.secretKey = @"SECRETKEY"; // 密钥 Token(如果使用永久密钥不需要填入 token,如果使用临时密钥需要填入) credential.token = @"TOKEN"; // 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数 startTime 和 expiredTime 单位为秒) credential.startDate = [NSDate dateWithTimeIntervalSince1970:startTime]; // 单位是秒 credential.expirationDate = [NSDate dateWithTimeIntervalSince1970:expiredTime];// 单位是秒 QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc] initWithCredential:credential]; // SDK 中默认下面所有 Header 都参与签名,无需设置。 // 若需制定某个 Header 不参与签名,则将相应的 Header 从下面数组中删除,然后赋值给 shouldSignedList 即可。 // creator.shouldSignedList = @[@"Cache-Control", @"Content-Disposition", @"Content-Encoding", @"Content-Length", @"Content-MD5", @"Content-Type", @"Expect", @"Expires", @"If-Match" , @"If-Modified-Since" , @"If-None-Match" , @"If-Unmodified-Since" , @"Origin" , @"Range" , @"transfer-encoding" ,@"Host",@"Pic-Operations",@"ci-process"]; // 注意 这里不要对 urlRequst 进行 copy 以及 mutableCopy 操作 QCloudSignature *signature = [creator signatureForData:urlRequst]; continueBlock(signature, nil);}@end//AppDelegate.swift//AppDelegate 需遵循 QCloudSignatureProvider class AppDelegate: UIResponder, UIApplicationDelegate, QCloudSignatureProvider { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); endpoint.regionName = "COS_REGION"; endpoint.useHTTPS = true; config.endpoint = endpoint; // 设置密钥回调代理 config.signatureProvider = self; QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger( with: config); return true } // 密钥回调的代理方法 func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { /** * 此处获取密钥,如果使用永久密钥则忽略 * … */ /** * 此处既可以是临时密钥也可以是永久密钥 * 临时密钥获取见:https://cloud.tencent.com/document/product/436/14048 * 注意:永久密钥不可用于生产环境,仅可作为调试使用 */ let credential = QCloudCredential.init(); // 密钥 SecretId credential.secretID = "SECRETID"; // 密钥 SecretKey credential.secretKey = "SECRETKEY"; // 密钥 Token(如果使用永久密钥不需要填入,如果使用临时密钥需要填入) credential.token = "TOKEN"; // 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数 startTime 和 expiredTime 单位为秒) credential.startDate = Date.init(timeIntervalSince1970: TimeInterval(startTime)!); credential.expirationDate = Date.init(timeIntervalSince1970: TimeInterval(expiredTime)!); let creator = QCloudAuthentationV5Creator.init(credential: credential); // 注意:这里不要对 urlRequst 进行 copy 以及 mutableCopy 操作 let signature = creator?.signature(forData: urlRequst); continueBlock(signature,nil); }}import SwiftUIimport QCloudCOSXML@mainstruct SwiftUIDemoApp: App { init() { // 在应用初始化时调用 SDK 配置 COSManager.shared.setupCOSSDK(); } var body: some Scene { WindowGroup { ContentView() } }}// COSManager需遵循QCloudSignatureProviderclass COSManager: NSObject, QCloudSignatureProvider { static let shared = COSManager() private override init() {} func setupCOSSDK() { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); endpoint.regionName = "COS_REGION"; endpoint.useHTTPS = true; config.endpoint = endpoint; config.signatureProvider = self; QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: config); } // 密钥回调的代理方法 func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { /** * 此处获取密钥,如果使用永久密钥则忽略 * … */ /** * 此处既可以是临时密钥也可以是永久密钥 * 临时密钥获取见:https://cloud.tencent.com/document/product/436/14048 * 注意:永久密钥不可用于生产环境,仅可作为调试使用 */ let credential = QCloudCredential.init(); // 密钥 SecretId credential.secretID = "SECRETID"; // 密钥 SecretKey credential.secretKey = "SECRETKEY"; // 密钥 Token(如果使用永久密钥不需要填入,如果使用临时密钥需要填入) credential.token = "TOKEN"; // 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数 startTime 和 expiredTime 单位为秒) credential.startDate = Date.init(timeIntervalSince1970: TimeInterval(startTime)!) DateFormatter().date(from: "startTime"); credential.expirationDate = Date.init(timeIntervalSince1970: TimeInterval(expiredTime)!) let creator = QCloudAuthentationV5Creator.init(credential: credential); // 注意:这里不要对 urlRequst 进行 copy 以及 mutableCopy 操作 let signature = creator?.signature(forData: urlRequst); continueBlock(signature,nil); }}说明:此外 SDK 还提供了栅栏机制(QCloudCredentailFenceQueue),所有获取签名的请求会等待签名完成后在执行,免去了自己管理异步过程。注意:栅栏机制仅针对密钥回调这种方式有效并且仅适用客户端管理密钥的情况。栅栏机制的使用如下:Objective-CSwiftSwiftUI// AppDelegate需遵循QCloudCredentailFenceQueueDelegate@interface AppDelegate () <QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate>// 控制栅栏机制的对象@property (nonatomic, strong) QCloudCredentailFenceQueue *credentialFenceQueue;@end@implementation AppDelegate- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions { // … SDK 初始化相关的流程此处省略 self.credentialFenceQueue = [QCloudCredentailFenceQueue new]; // 设置栅栏机制的代理对象 self.credentialFenceQueue.delegate = self; return YES;}// 密钥回调代理中需要使用栅栏对象获取签名- (void)signatureWithFields:(QCloudSignatureFields *)fileds request:(QCloudBizHTTPRequest *)request urlRequest:(NSMutableURLRequest *)urlRequst compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock { [self.credentialFenceQueue performAction:^(QCloudAuthentationCreator *creator, NSError *error) { if (error) { continueBlock(nil, error); } else { QCloudSignature *signature = [creator signatureForData:urlRequst]; continueBlock(signature, nil); } }];}// 栅栏机制的回调代理中获取密钥- (void)fenceQueue:(QCloudCredentailFenceQueue *)queue requestCreatorWithContinue:(QCloudCredentailFenceQueueContinue)continueBlock { [[[NSURLSession sharedSession]dataTaskWithURL:[NSURL URLWithString:@"https://******"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 从业务服务接口请求临时密钥。 NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingTopLevelDictionaryAssumed error:nil]; NSDictionary * credentials = dic[@"credentials"]; QCloudCredential *credential = [QCloudCredential new]; credential.secretID = credentials[@"tmpSecretId"]; credential.secretKey = credentials[@"tmpSecretKey"];; credential.token = credentials[@"sessionToken"];; //签名过期时间 credential.expirationDate = nil; credential.startDate = nil; QCloudAuthentationV5Creator *creator = [[QCloudAuthentationV5Creator alloc] initWithCredential:credential]; continueBlock(creator, nil); }] resume];}@endimport UIKitimport QCloudCOSXML@mainclass AppDelegate: UIResponder, UIApplicationDelegate, QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate { var window: UIWindow? var credentialFenceQueue: QCloudCredentailFenceQueue! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // … SDK 初始化相关的流程此处省略 credentialFenceQueue = QCloudCredentailFenceQueue() credentialFenceQueue.delegate = self return true } // MARK: – QCloudSignatureProvider func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { credentialFenceQueue.performAction { (creator: QCloudAuthentationCreator?, error: Error?) in if let error = error { continueBlock(nil, error) } else if let creator = creator { let signature = creator.signature(for: urlRequst) continueBlock(signature, nil) } } } // MARK: – QCloudCredentailFenceQueueDelegate func fenceQueue(_ queue: QCloudCredentailFenceQueue!, requestCreatorWithContinue continueBlock: QCloudCredentailFenceQueueContinue!) { // 构建请求临时密钥的 URL (请替换为你实际的服务器地址) guard let url = URL(string: "https://******") else { // 处理 URL 构造失败 let error = NSError(domain: "AppDelegate", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL for temporary key"]) continueBlock(nil, error) return } let task = URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in // 处理网络错误 if let error = error { continueBlock(nil, error) return } // 确保数据存在 guard let data = data else { let error = NSError(domain: "AppDelegate", code: -2, userInfo: [NSLocalizedDescriptionKey: "No data received from server"]) continueBlock(nil, error) return } do { // 解析 JSON 数据 if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let credentials = json["credentials"] as? [String: Any], let tmpSecretId = credentials["tmpSecretId"] as? String, let tmpSecretKey = credentials["tmpSecretKey"] as? String, let sessionToken = credentials["sessionToken"] as? String { // 创建 QCloudCredential 对象并设置临时密钥 let credential = QCloudCredential() credential.secretID = tmpSecretId credential.secretKey = tmpSecretKey credential.token = sessionToken // 如果服务器返回了 startTime 和 expiredTime,建议设置 // credential.startDate = Date(timeIntervalSince1970: startTime) // credential.expirationDate = Date(timeIntervalSince1970: expiredTime) let creator = QCloudAuthentationV5Creator(credential: credential) continueBlock(creator, nil) } else { // JSON 解析失败或键值缺失 let error = NSError(domain: "AppDelegate", code: -3, userInfo: [NSLocalizedDescriptionKey: "Failed to parse temporary key response"]) continueBlock(nil, error) } } catch { // JSON 解析异常 continueBlock(nil, error) } } task.resume() // 启动网络任务 }}import SwiftUIimport QCloudCOSXML@mainstruct SwiftUIDemoApp: App { init() { // 在应用初始化时调用 SDK 配置 COSManager.shared.setupCOSSDK(); } var body: some Scene { WindowGroup { ContentView() } }}class COSManager: NSObject, QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate { static let shared = COSManager() private let credentialFenceQueue = QCloudCredentailFenceQueue() private override init() {} func setupCOSSDK() { // … SDK 初始化相关的流程此处省略 credentialFenceQueue.delegate = self } // MARK: – QCloudSignatureProvider func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { credentialFenceQueue.performAction { (creator: QCloudAuthentationCreator?, error: Error?) in if let error = error { continueBlock(nil, error) } else if let creator = creator { let signature = creator.signature(for: urlRequst) continueBlock(signature, nil) } } } // MARK: – QCloudCredentailFenceQueueDelegate func fenceQueue(_ queue: QCloudCredentailFenceQueue!, requestCreatorWithContinue continueBlock: QCloudCredentailFenceQueueContinue!) { // 构建请求临时密钥的 URL (请替换为你实际的服务器地址) guard let url = URL(string: "https://******") else { // 处理 URL 构造失败 let error = NSError(domain: "AppDelegate", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL for temporary key"]) continueBlock(nil, error) return } let task = URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in // 处理网络错误 if let error = error { continueBlock(nil, error) return } // 确保数据存在 guard let data = data else { let error = NSError(domain: "AppDelegate", code: -2, userInfo: [NSLocalizedDescriptionKey: "No data received from server"]) continueBlock(nil, error) return } do { // 解析 JSON 数据 if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let credentials = json["credentials"] as? [String: Any], let tmpSecretId = credentials["tmpSecretId"] as? String, let tmpSecretKey = credentials["tmpSecretKey"] as? String, let sessionToken = credentials["sessionToken"] as? String { // 创建 QCloudCredential 对象并设置临时密钥 let credential = QCloudCredential() credential.secretID = tmpSecretId credential.secretKey = tmpSecretKey credential.token = sessionToken // 如果服务器返回了 startTime 和 expiredTime,建议设置 // credential.startDate = Date(timeIntervalSince1970: startTime) // credential.expirationDate = Date(timeIntervalSince1970: expiredTime) let creator = QCloudAuthentationV5Creator(credential: credential) continueBlock(creator, nil) } else { // JSON 解析失败或键值缺失 let error = NSError(domain: "AppDelegate", code: -3, userInfo: [NSLocalizedDescriptionKey: "Failed to parse temporary key response"]) continueBlock(nil, error) } } catch { // JSON 解析异常 continueBlock(nil, error) } } task.resume() // 启动网络任务 } }Objective-CSwiftSwiftUI//AppDelegate.m//AppDelegate 需遵循 QCloudSignatureProvider @interface AppDelegate()<QCloudSignatureProvider>@end@implementation AppDelegate- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions { QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new]; QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] init]; // 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket // COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = @"COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; configuration.endpoint = endpoint; // 密钥提供者为自己 configuration.signatureProvider = self; // 初始化 COS 服务示例 [QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration]; [QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration: configuration]; return YES;}- (void)signatureWithFields:(QCloudSignatureFields*)fileds request:(QCloudBizHTTPRequest*)request urlRequest:(NSMutableURLRequest*)urlRequst compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock{ // 签名过期时间 NSDate *expiration = [[[NSDateFormatter alloc] init] dateFromString:@"expiredTime"]; QCloudSignature *signature = [[QCloudSignature alloc] initWithSignature: @"后台计算好的签名" expiration:expiration]; signature.token = @"临时密钥Token";// 永久密钥不需要 Token continueBlock(signature, nil);}@end//AppDelegate.swift//AppDelegate 需遵循 QCloudSignatureProvider class AppDelegate: UIResponder, UIApplicationDelegate, QCloudSignatureProvider { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); // 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket // COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = "COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; config.endpoint = endpoint; // 密钥提供者为自己 config.signatureProvider = self; // 初始化 COS 服务示例 QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger( with: config); return true } func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { // 签名过期时间 let expiration = DateFormatter().date(from: "expiredTime"); let signature = QCloudSignature.init(signature: "后台计算好的签名", expiration: expiration); signature.token = "临时密钥Token";// 永久密钥不需要 Token continueBlock(signature,nil); } }import SwiftUIimport QCloudCOSXML@mainstruct SwiftUIDemoApp: App { init() { // 在应用初始化时调用 SDK 配置 COSManager.shared.setupCOSSDK(); } var body: some Scene { WindowGroup { ContentView() } }}class COSManager: NSObject, QCloudSignatureProvider { static let shared = COSManager() private override init() {} func setupCOSSDK() { let config = QCloudServiceConfiguration.init(); let endpoint = QCloudCOSXMLEndPoint.init(); // 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket // COS 支持的所有 region 列表参见 https://www.qcloud.com/document/product/436/6224 endpoint.regionName = "COS_REGION"; // 使用 HTTPS endpoint.useHTTPS = true; config.endpoint = endpoint; config.signatureProvider = self; // 初始化 COS 服务示例 QCloudCOSXMLService.registerDefaultCOSXML(with: config); QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: config); } // 获取签名的方法入口,这里演示了获取临时密钥并计算签名的过程 // 你也可以自定义计算签名的过程 func signature(with fileds: QCloudSignatureFields!, request: QCloudBizHTTPRequest!, urlRequest urlRequst: NSMutableURLRequest!, compelete continueBlock: QCloudHTTPAuthentationContinueBlock!) { // 签名过期时间 let expiration = DateFormatter().date(from: "expiredTime"); let signature = QCloudSignature.init(signature: "后台计算好的签名", expiration: expiration); signature.token = "临时密钥Token";// 永久密钥不需要 Token continueBlock(signature,nil); }}
八、配置域名
SDK 支持自定义域名访问 COS 的相关服务。
使用方式:在“初始化 COS 服务”步骤中,实例化 QCloudCOSXMLEndPoint 时传入指定的域名。
注意:说明:
Objective-CSwiftNSString *customDomain = @"exampledomain.com"; // 自定义源站域名或全球加速域名QCloudCOSXMLEndPoint *endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:customDomain]];QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];// 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket// COS 支持的所有 region 列表参见https://www.qcloud.com/document/product/436/6224// 使用 HTTPSendpoint.regionName = @"COS_REGION";endpoint.useHTTPS = true;configuration.endpoint = endpoint;// 初始化 COS 服务示例[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];[QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration: configuration];let endpoint = QCloudCOSXMLEndPoint.init(literalURL: NSURL.init(string: "exampledomain.com") as URL?);let config = QCloudServiceConfiguration.init();// 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket// COS 支持的所有 region 列表参见https://www.qcloud.com/document/product/436/6224// 使用 HTTPSendpoint.useHTTPS = true;endpoint.regionName = "COS_REGION";config.endpoint = endpoint;// 初始化 COS 服务示例QCloudCOSXMLService.registerDefaultCOSXML(with: config);QCloudCOSTransferMangerService.registerDefaultCOSTransferManger( with: config);
九、配置并发(可选)
SDK 支持自定义请求并发数。
使用方式:在“初始化 COS 服务”步骤中,自定义并发数以及并发数自增上限。
注意:说明:
注意:SDK 内部请求为多线程并发请求,并发数默认1,并且根据实时网速进行自动增减,最小1,最大4。
Objective-CSwift// 设置并发数4[QCloudHTTPSessionManager shareClient].customConcurrentCount = 4;// 设置自动上限8[QCloudHTTPSessionManager shareClient].maxConcurrencyTask = 4;// 设置并发数4QCloudHTTPSessionManager.shareClient.customConcurrentCount = 4;// 设置自动上限8QCloudHTTPSessionManager.shareClient.maxConcurrencyTask = 4;
十、访问 COS 服务
以文件上传/下载为例介绍如何访问 SDK 的相关服务。
文件上传文件下载SDK 支持上传本地文件与二进制数据 NSData。下面以上传本地文件为例。Objective-CSwiftQCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];// 本地文件路径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:^(id outputObject, NSError *error) { //可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息 NSDictionary * result = (NSDictionary *)outputObject;}];[[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 error != nil{ print(error!); }else{ print(result!); }}//监听上传进度put.sendProcessBlock = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) in // bytesSent 本次要发送的字节数(一个大文件可能要分多次发送) // totalBytesSent 已发送的字节数 // totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)};//设置上传参数put.initMultipleUploadFinishBlock = {(multipleUploadInitResult, resumeData) in //在初始化分块上传完成以后会回调该 block,在这里可以获取 resumeData //并且可以通过 resumeData 生成一个分块上传的请求 let resumeUploadRequest = QCloudCOSXMLUploadObjectRequest<AnyObject> .init(request: resumeData as Data?);}QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(put);Objective-CSwiftQCloudCOSXMLDownloadObjectRequest * request = [QCloudCOSXMLDownloadObjectRequest new];// 存储桶名称,由 BucketName-Appid 组成,可以在 COS 控制台查看 https://console.cloud.tencent.com/cos5/bucketrequest.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"request.object = @"exampleobject";//设置下载的路径 URL,如果设置了,文件将会被下载到指定路径中request.downloadingURL = [NSURL fileURLWithPath:@"Local File Path"];//监听下载结果[request setFinishBlock:^(id outputObject, NSError *error) { //outputObject 包含所有的响应 http 头部 NSDictionary* info = (NSDictionary *) outputObject;}];//监听下载进度[request setDownProcessBlock:^(int64_t bytesDownload, int64_t totalBytesDownload, int64_t totalBytesExpectedToDownload) { // bytesDownload 本次要下载的字节数(一个大文件可能要分多次发送) // totalBytesDownload 已下载的字节数 // totalBytesExpectedToDownload 本次要下载的总字节数(即一个文件大小)}];[[QCloudCOSTransferMangerService defaultCOSTransferManager] DownloadObject:request];let request : QCloudCOSXMLDownloadObjectRequest = QCloudCOSXMLDownloadObjectRequest();// 存储桶名称,由 BucketName-Appid 组成,可以在 COS 控制台查看 https://console.cloud.tencent.com/cos5/bucketrequest.bucket = "examplebucket-1250000000";// 对象键request.object = "exampleobject";//设置下载的路径 URL,如果设置了,文件将会被下载到指定路径中request.downloadingURL = NSURL.fileURL(withPath: "Local File Path") as URL?;//监听下载进度request.downProcessBlock = { (bytesDownload, totalBytesDownload, totalBytesExpectedToDownload) in // bytesDownload 本次要下载的字节数(一个大文件可能要分多次发送) // totalBytesDownload 已下载的字节数 // totalBytesExpectedToDownload 本次要下载的总字节数(即一个文件大小)}//监听下载结果request.finishBlock = { (copyResult, error) in if error != nil{ print(error!); }else{ print(copyResult!); }}QCloudCOSTransferMangerService.defaultCOSTransferManager().downloadObject(request);
注意:说明:
十一、常见问题
如果你在使用 XML 版本 SDK 时遇到函数或方法不存在等错误,请先将 XML 版本 SDK 升级到最新版再重试。如果你仍在使用 JSON 版本 SDK,请 升级到 XML iOS SDK。