更换腾讯cos上传

This commit is contained in:
启星
2025-10-24 10:52:40 +08:00
parent 22ba9e1070
commit 3a5cf56099
415 changed files with 47343 additions and 11864 deletions

View File

@@ -56,6 +56,9 @@ def taget_pods
pod 'JXPagingView/Pager' pod 'JXPagingView/Pager'
#阿里云上传文件 #阿里云上传文件
pod 'AliyunOSSiOS' pod 'AliyunOSSiOS'
#腾讯cos
pod 'QCloudCOSXML/Transfer'
#声网
pod 'AgoraRtcEngine_iOS','~> 4.5.2' pod 'AgoraRtcEngine_iOS','~> 4.5.2'
# pod 'AgoraRtcEngine_Special_iOS','~> 4.4.1.9' # pod 'AgoraRtcEngine_Special_iOS','~> 4.4.1.9'
# pod 'AgoraRtm_iOS' # pod 'AgoraRtm_iOS'

View File

@@ -167,6 +167,9 @@ PODS:
- MQTTClient/Min - MQTTClient/Min
- MQTTClient/Min (0.15.3) - MQTTClient/Min (0.15.3)
- Protobuf (3.29.3) - Protobuf (3.29.3)
- QCloudCore/WithoutMTA (6.5.0)
- QCloudCOSXML/Transfer (6.5.0):
- QCloudCore/WithoutMTA (= 6.5.0)
- QGVAPlayer (1.0.19) - QGVAPlayer (1.0.19)
- ReactiveObjC (3.1.1) - ReactiveObjC (3.1.1)
- SDCycleScrollView (1.82): - SDCycleScrollView (1.82):
@@ -260,6 +263,7 @@ DEPENDENCIES:
- MBProgressHUD - MBProgressHUD
- MJRefresh - MJRefresh
- MQTTClient - MQTTClient
- QCloudCOSXML/Transfer
- QGVAPlayer - QGVAPlayer
- SDCycleScrollView - SDCycleScrollView
- SDWebImage - SDWebImage
@@ -305,6 +309,8 @@ SPEC REPOS:
- MJRefresh - MJRefresh
- MQTTClient - MQTTClient
- Protobuf - Protobuf
- QCloudCore
- QCloudCOSXML
- QGVAPlayer - QGVAPlayer
- ReactiveObjC - ReactiveObjC
- SDCycleScrollView - SDCycleScrollView
@@ -359,6 +365,8 @@ SPEC CHECKSUMS:
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
MQTTClient: 0dfa04e789479c2e461786464969895c1fcb0875 MQTTClient: 0dfa04e789479c2e461786464969895c1fcb0875
Protobuf: e2de96d939c642ce8da186343ff8929b35223212 Protobuf: e2de96d939c642ce8da186343ff8929b35223212
QCloudCore: 8681c29dc68d783d07209e7a6ebd8b9058ec73e8
QCloudCOSXML: 26ba1918f7126e650e70f091fee4760cca38038a
QGVAPlayer: a0bca68c9bd6f1c8de5ac2d10ddf98be6038cce9 QGVAPlayer: a0bca68c9bd6f1c8de5ac2d10ddf98be6038cce9
ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040 ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040
SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf
@@ -384,6 +392,6 @@ SPEC CHECKSUMS:
YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928 YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928
Zip: b3fef584b147b6e582b2256a9815c897d60ddc67 Zip: b3fef584b147b6e582b2256a9815c897d60ddc67
PODFILE CHECKSUM: 0d9fb42b40922f1e7b70bca0655faf5be6d1d454 PODFILE CHECKSUM: 0bc5dc8150dc827b074af9f826d3454f1feacf07
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

10
Pods/Manifest.lock generated
View File

@@ -167,6 +167,9 @@ PODS:
- MQTTClient/Min - MQTTClient/Min
- MQTTClient/Min (0.15.3) - MQTTClient/Min (0.15.3)
- Protobuf (3.29.3) - Protobuf (3.29.3)
- QCloudCore/WithoutMTA (6.5.0)
- QCloudCOSXML/Transfer (6.5.0):
- QCloudCore/WithoutMTA (= 6.5.0)
- QGVAPlayer (1.0.19) - QGVAPlayer (1.0.19)
- ReactiveObjC (3.1.1) - ReactiveObjC (3.1.1)
- SDCycleScrollView (1.82): - SDCycleScrollView (1.82):
@@ -260,6 +263,7 @@ DEPENDENCIES:
- MBProgressHUD - MBProgressHUD
- MJRefresh - MJRefresh
- MQTTClient - MQTTClient
- QCloudCOSXML/Transfer
- QGVAPlayer - QGVAPlayer
- SDCycleScrollView - SDCycleScrollView
- SDWebImage - SDWebImage
@@ -305,6 +309,8 @@ SPEC REPOS:
- MJRefresh - MJRefresh
- MQTTClient - MQTTClient
- Protobuf - Protobuf
- QCloudCore
- QCloudCOSXML
- QGVAPlayer - QGVAPlayer
- ReactiveObjC - ReactiveObjC
- SDCycleScrollView - SDCycleScrollView
@@ -359,6 +365,8 @@ SPEC CHECKSUMS:
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
MQTTClient: 0dfa04e789479c2e461786464969895c1fcb0875 MQTTClient: 0dfa04e789479c2e461786464969895c1fcb0875
Protobuf: e2de96d939c642ce8da186343ff8929b35223212 Protobuf: e2de96d939c642ce8da186343ff8929b35223212
QCloudCore: 8681c29dc68d783d07209e7a6ebd8b9058ec73e8
QCloudCOSXML: 26ba1918f7126e650e70f091fee4760cca38038a
QGVAPlayer: a0bca68c9bd6f1c8de5ac2d10ddf98be6038cce9 QGVAPlayer: a0bca68c9bd6f1c8de5ac2d10ddf98be6038cce9
ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040 ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040
SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf
@@ -384,6 +392,6 @@ SPEC CHECKSUMS:
YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928 YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928
Zip: b3fef584b147b6e582b2256a9815c897d60ddc67 Zip: b3fef584b147b6e582b2256a9815c897d60ddc67
PODFILE CHECKSUM: 0d9fb42b40922f1e7b70bca0655faf5be6d1d454 PODFILE CHECKSUM: 0bc5dc8150dc827b074af9f826d3454f1feacf07
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
//
// NSString+RegularExpressionCategory.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 29/06/2018.
//
#import <Foundation/Foundation.h>
@interface NSString (RegularExpressionCategory)
- (BOOL)matchesRegularExpression:(NSString *)regularExpression;
@end

View File

@@ -0,0 +1,15 @@
//
// NSString+RegularExpressionCategory.m
// QCloudCOSXML
//
// Created by erichmzhang() on 29/06/2018.
//
#import "NSString+RegularExpressionCategory.h"
@implementation NSString (RegularExpressionCategory)
- (BOOL)matchesRegularExpression:(NSString *)regularExpression {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regularExpression];
return [predicate evaluateWithObject:self];
}
@end

View File

@@ -0,0 +1,16 @@
//
// QCloudAbstractRequest+Quality.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 2018/8/24.
//
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface QCloudAbstractRequest (Quality)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
//
// QCloudAbstractRequest+Quality.m
// QCloudCOSXML
//
// Created by erichmzhang() on 2018/8/24.
//
#import "QCloudAbstractRequest+Quality.h"
#import <objc/runtime.h>
#import <QCloudCore/QualityDataUploader.h>
#import "QCloudCOSXMLVersion.h"
#import "QCloudCOSXMLService+Quality.h"
@interface QCloudAbstractRequest ()
@end
@implementation QCloudAbstractRequest (Quality)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self exchangeImplementation];
});
}
+ (void)exchangeImplementation {
Class class = [self class];
Method originNotifyErrorMethod = class_getInstanceMethod(class, @selector(__notifyError:));
Method swizzedNotifyErrorMethod = class_getInstanceMethod(class, @selector(__quality__notifyError:));
Method originNotifySuccessMethod = class_getInstanceMethod(class, @selector(__notifySuccess:));
Method swizzedNotifySuccessMethod = class_getInstanceMethod(class, @selector(__quality__notifySuccess:));
method_exchangeImplementations(originNotifyErrorMethod, swizzedNotifyErrorMethod);
method_exchangeImplementations(originNotifySuccessMethod, swizzedNotifySuccessMethod);
}
- (void)__quality__notifyError:(NSError *)error {
[self __quality__notifyError:error];
[QualityDataUploader trackSDKRequestFailWithRequest:self error:error params:[QCloudCOSXMLService commonParams:kQCloudDataAppReleaseKey]];
}
- (void)__quality__notifySuccess:(id)object {
[self __quality__notifySuccess:object];
[QualityDataUploader trackSDKRequestSuccessWithRequest:self params:[QCloudCOSXMLService commonParams:kQCloudDataAppReleaseKey]];
}
@end

View File

@@ -0,0 +1,16 @@
//
// QCloudBizHTTPRequest+COSXML.h
// QCloudCOSXML
//
// Created by garenwang on 2025/3/28.
//
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface QCloudBizHTTPRequest (COSXML)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,132 @@
//
// QCloudBizHTTPRequest+COSXML.m
// QCloudCOSXML
//
// Created by garenwang on 2025/3/28.
//
#import "QCloudBizHTTPRequest+COSXML.h"
#import <QCloudCore/QCloudHTTPRetryHanlder.h>
#import "QCloudCOSXMLEndPoint.h"
@implementation QCloudBizHTTPRequest (COSXML)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(buildRequestData:);
SEL swizzledSelector = @selector(cos_buildRequestData:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod
= class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (BOOL)cos_buildRequestData:(NSError *__autoreleasing *)error{
BOOL ret = [self cos_buildRequestData:error];
if (!ret) {
return ret;
}
if (self.runOnService.configuration.networkStrategy != QCloudRequestNetworkStrategyDefault){
NSString * bucket = nil;
if ([self respondsToSelector:@selector(bucket)]) {
bucket = [self performSelector:@selector(bucket)];
}else if ([self respondsToSelector:@selector(bucketName)]) {
bucket = [self performSelector:@selector(bucketName)];
}else if ([self respondsToSelector:@selector(BucketName)]) {
bucket = [self performSelector:@selector(BucketName)];
}
NSString * appId = self.runOnService.configuration.appID;
NSString * regionName = self.regionName;
if (!regionName) {
regionName = self.runOnService.configuration.endpoint.regionName;
}
BOOL useHTTPS = self.runOnService.configuration.endpoint.useHTTPS;
if (self.endpoint) {
useHTTPS = self.endpoint.useHTTPS;
}
if (self.requestRetry) {
if (self.runOnService.configuration.networkStrategy == QCloudRequestNetworkStrategyConservative){
if (self.networkType != QCloudRequestNetworkNone) {
self.enableQuic = self.networkType == QCloudRequestNetworkQuic;
}else {
self.enableQuic = self.runOnService.configuration.enableQuic;
}
if (self.endpoint) {
self.requestData.endpoint = self.endpoint;
}else{
self.requestData.endpoint = self.runOnService.configuration.endpoint;
}
}else if (self.runOnService.configuration.networkStrategy == QCloudRequestNetworkStrategyAggressive){
self.enableQuic = NO;
QCloudCOSXMLEndPoint * endpoint = [[QCloudCOSXMLEndPoint alloc]init];
endpoint.useHTTPS = useHTTPS;
endpoint.regionName = regionName;
self.requestData.endpoint = endpoint;
}
}else{
if (self.runOnService.configuration.networkStrategy == QCloudRequestNetworkStrategyConservative){
self.enableQuic = NO;
QCloudCOSXMLEndPoint * endpoint = [[QCloudCOSXMLEndPoint alloc]init];
endpoint.useHTTPS = useHTTPS;
endpoint.regionName = regionName;
self.requestData.endpoint = endpoint;
}else if (self.runOnService.configuration.networkStrategy == QCloudRequestNetworkStrategyAggressive){
if (self.networkType != QCloudRequestNetworkNone) {
self.enableQuic = self.networkType == QCloudRequestNetworkQuic;
}else {
self.enableQuic = self.runOnService.configuration.enableQuic;
}
if (self.endpoint) {
self.requestData.endpoint = self.endpoint;
}else{
self.requestData.endpoint = self.runOnService.configuration.endpoint;
}
}
}
self.requestData.bucket = bucket;
self.requestData.appId = appId;
self.requestData.region = regionName;
}
QCloudLogDebugP(@"HTTP",@"buildRequestData——当前策略%@,是否已重试:%@", QCloudNetworkSituationToString(self.runOnService.configuration.networkStrategy),self.requestRetry?@"是":@"否");
return YES;
}
- (void)notifyError:(NSError *)error {
QCloudRequestFinishBlock finishBlock = self.finishBlock;
BOOL is4XX = error.code >= 400 && error.code <500;
QCloudLogDebugP(@"HTTP",@"notifyError——当前策略%@,是否已重试:%@", QCloudNetworkSituationToString(self.runOnService.configuration.networkStrategy),self.requestRetry?@"是":@"否");
if (is4XX || self.runOnService.configuration.networkStrategy == QCloudRequestNetworkStrategyDefault ||
self.requestRetry ) {
[super notifyError:error];
}else{
[self.retryPolicy reset];
[self.requestData clean];
[self setValue:@(NO) forKey:@"isRetry"];
self.retryCount = 0;
self.requestRetry = YES;
self.finishBlock = finishBlock;
[self.runOnService requestFinishWithRequestId:self.requestID];
self.priority = QCloudAbstractRequestPriorityHigh;
[self.runOnService performRequest:self];
}
}
@end

View File

@@ -0,0 +1,43 @@
//
// QCloudCOSXMLEndPoint.h
// Pods
//
// Created by Dong Zhao on 2017/8/22.
//
//
#import <QCloudCore/QCloudCore.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-property-synthesis"
/**
QCloudServiceConfiguration 类的 endpoint 参数
*/
@interface QCloudCOSXMLEndPoint : QCloudEndPoint
/**
* 服务地域名称,可用的服务地域名称请查看官网https://www.qcloud.com/document/product/436/6224
* 中提供的地域这里填入官网里提供的地域简称例如ap-beijing等。
*/
@property (nonatomic, copy) QCloudRegion regionName;
@property (nonatomic, assign) BOOL isPrefixURL;
/**
服务的基础名称, 默认值为: myqcloud.com
*/
@property (nonatomic, copy) QCloudServiceName serviceName;
/**
自定义域名http://bucketname.suffix
未指定该参数该存储桶host为 http://bucketname.****
指定该参数为testsuffix该存储桶host为 http://bucketname.testsuffix.****
*/
@property (nonatomic, copy) NSString *suffix;
///**
// 是否切换到旧域名
// */
//@property (nonatomic, assign) BOOL enableOldDomain;
- (NSURL *)serverURLWithProductName:(NSString *)productName AppID:(NSString *)appID regionName:(NSString *)regionName;
@end
#pragma clang diagnostic pop

View File

@@ -0,0 +1,137 @@
//
// QCloudCOSXMLEndPoint.m
// Pods
//
// Created by Dong Zhao on 2017/8/22.
//
//
#import "QCloudCOSXMLEndPoint.h"
#import "NSString+RegularExpressionCategory.h"
@implementation QCloudCOSXMLEndPoint
- (instancetype)init {
self = [super init];
if (!self) {
return self;
}
_isPrefixURL = YES;
_serviceName = @"myqcloud.com";
return self;
}
//-(void)setEnableOldDomain:(BOOL)enableOldDomain{
// _enableOldDomain = enableOldDomain;
// if(_enableOldDomain){
// _serviceName = @"myqcloud.com";
//
// }else{
// _serviceName = @"tencentcos.cn";
// }
//}
- (NSString *)formattedBucket:(NSString *)bucket withAPPID:(NSString *)APPID {
NSInteger subfixLength = APPID.length + 1;
if (bucket.length <= subfixLength) {
return bucket;
}
NSString *APPIDSubfix = [NSString stringWithFormat:@"-%@", APPID];
if (APPIDSubfix) {
NSString *subfixString = [bucket substringWithRange:NSMakeRange(bucket.length - subfixLength, subfixLength)];
if ([subfixString isEqualToString:APPIDSubfix]) {
return [bucket substringWithRange:NSMakeRange(0, bucket.length - subfixLength)];
}
} else {
if (!APPID) {
@throw [NSException exceptionWithName:kQCloudNetworkDomain
reason:[NSString stringWithFormat:@"您没有配置AppID就使用了服务%@", self.class]
userInfo:nil];
}
}
// should not reach here
return bucket;
}
- (NSURL *)serverURLWithBucket:(NSString *)bucket appID:(NSString *)appID regionName:(NSString *)regionName {
if (self.serverURLLiteral) {
return self.serverURLLiteral;
}
NSString *scheme = @"https";
if (!self.useHTTPS) {
scheme = @"http";
}
static NSString *regularExpression = @"[a-zA-Z0-9.-]*";
BOOL isLegal = [bucket matchesRegularExpression:regularExpression];
NSAssert(isLegal, @"bucket name contains illegal character! It can only contains a-z, A-Z, 0-9, '.' and '-' ");
if (!isLegal) {
QCloudLogDebugE(@"Service",@"bucket %@ contains illeagal character, building service url pregress returns immediately", bucket);
return nil;
}
NSString *formattedBucketName = [self formattedBucket:bucket withAPPID:appID];
if (appID) {
formattedBucketName = [NSString stringWithFormat:@"%@-%@", formattedBucketName, appID];
}
NSString *regionNametmp = nil;
if (regionName) {
regionNametmp = regionName;
} else {
regionNametmp = self.regionName;
}
if ([self.serviceName isEqualToString:@"myqcloud.com"]) {
NSParameterAssert(regionNametmp);
static NSString *regularExpression = @"[a-zA-Z0-9.-]*";
BOOL isLegal = [regionNametmp matchesRegularExpression:regularExpression];
NSAssert(isLegal, @"Region name contains illegal character! It can only contains a-z, A-Z, 0-9, '.' and '-' ");
if (!isLegal) {
QCloudLogDebugE(@"Service",@"Region %@ contains illeagal character, setter returns immediately", regionName);
return nil;
}
}
NSURL *serverURL;
serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@.cos.%@.%@", scheme, formattedBucketName, regionNametmp, self.serviceName]];
if (!self.isPrefixURL) {
serverURL =
[NSURL URLWithString:[NSString stringWithFormat:@"%@://%@.cos.%@/%@", scheme, regionNametmp, self.serviceName, formattedBucketName]];
}
if (self.suffix) {
serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@.%@", scheme, formattedBucketName, self.suffix]];
if (!self.isPrefixURL) {
serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", scheme, self.suffix, formattedBucketName]];
}
}
QCloudLogDebugP(@"Service",@"serverURL: %@", serverURL);
return serverURL;
}
- (void)setIsPrefixURL:(BOOL)isPrefixURL {
_isPrefixURL = isPrefixURL;
}
- (void)setRegionName:(QCloudRegion)regionName {
// Region a-z, A-Z, 0-9, . -
if ([self.serviceName isEqualToString:@"myqcloud.com"]) {
NSParameterAssert(regionName);
static NSString *regularExpression = @"[a-zA-Z0-9.-]*";
BOOL isLegal = [regionName matchesRegularExpression:regularExpression];
NSAssert(isLegal, @"Region name contains illegal character! It can only contains a-z, A-Z, 0-9, '.' and '-' ");
if (!isLegal) {
QCloudLogDebugE(@"Service",@"Region %@ contains illeagal character, setter returns immediately", regionName);
return;
}
}
_regionName = regionName;
}
- (id)copyWithZone:(NSZone *)zone {
QCloudCOSXMLEndPoint *endpoint = [super copyWithZone:nil];
endpoint.regionName = self.regionName;
endpoint.serviceName = self.serviceName;
endpoint.isPrefixURL = self.isPrefixURL;
endpoint.suffix = self.suffix;
// endpoint.enableOldDomain = self.enableOldDomain;
return endpoint;
}
@end

View File

@@ -0,0 +1,37 @@
//
// QCloudCOSXMLService.h
// QCloudCOSXMLService
//
// Created by tencent
//
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudService.h>
#import "QCloudCOSXMLService.h"
@interface QCloudCOSXMLService (Configuration)
@end

View File

@@ -0,0 +1,53 @@
//
// COSXML.m
// COSXML
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCOSXMLService+Configuration.h"
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudCOSXMLService+Private.h"
@implementation QCloudCOSXMLService (Configuration)
- (instancetype)initWithConfiguration:(QCloudServiceConfiguration *)configuration {
configuration = [configuration copy];
self = [super initWithConfiguration:configuration];
if (!self) {
return self;
}
return self;
}
- (void)loadAuthorizationForBiz:(QCloudBizHTTPRequest *)bizRequest
urlRequest:(NSMutableURLRequest *)urlrequest
compelete:(QCloudHTTPAuthentationContinueBlock)cotinueBlock {
[self loadCOSXMLAuthorizationForBiz:bizRequest urlRequest:urlrequest compelete:cotinueBlock];
}
@end

View File

@@ -0,0 +1,12 @@
//
// QCloudCOSXMLService+Private.h
// Pods
//
// Created by Dong Zhao on 2017/4/11.
//
//
@interface QCloudCOSXMLService ()
@end

View File

@@ -0,0 +1,15 @@
//
// QCloudCOSXML+Quality.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 2018/8/23.
//
#import <Foundation/Foundation.h>
#import "QCloudCOSXMLService.h"
extern NSString *const kQCloudDataAppReleaseKey;
@interface QCloudCOSXMLService (Quality)
+(NSMutableDictionary *)commonParams:(NSString *)appKey;
@end

View File

@@ -0,0 +1,66 @@
//
// QCloudCOSXML+Quality.m
// QCloudCOSXML
//
// Created by erichmzhang() on 2018/8/23.
//
#define kQAUploadStrategy @(2)
#import "QCloudCOSXMLService+Quality.h"
#import <objc/runtime.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudLogger.h>
#import "QCloudCOSXMLVersion.h"
#import <QCloudCore/QualityDataUploader.h>
#import <QCloudCore/QCloudServiceConfiguration+Quality.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
NSString *const kQCloudDataAppReleaseKey = @"0IOS05O9HW7A9XPI";
@implementation QCloudCOSXMLService (Quality)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self changeImplementation];
});
}
+ (void)changeImplementation {
Class class = object_getClass((id)self);
Method originMethod = class_getClassMethod(class, @selector(registerDefaultCOSXMLWithConfiguration:));
Method replacedMethod = class_getClassMethod(class, @selector(Quality_registerDefaultCOSXMLWithConfiguration:));
method_exchangeImplementations(originMethod, replacedMethod);
}
+ (QCloudCOSXMLService *)Quality_registerDefaultCOSXMLWithConfiguration:(QCloudServiceConfiguration *)configuration {
id result = [self Quality_registerDefaultCOSXMLWithConfiguration:configuration];
if(!configuration.disableSetupBeacon){
[self initMTA:configuration];
}
return result;
}
+ (void)initMTA:(QCloudServiceConfiguration *)configuration {
#if defined(DEBUG) && DEBUG
#else
NSMutableDictionary * commonParams = [self commonParams:nil];
commonParams[@"sdk_bridge"] = configuration.bridge?:@"";
[QualityDataUploader initCommonParams:commonParams];
[QualityDataUploader trackBaseInfoToTrachCommonParams:commonParams];
[QualityDataUploader startWithAppkey:kQCloudDataAppReleaseKey];
#endif
}
+(NSMutableDictionary *)commonParams:(NSString *)appKey{
NSMutableDictionary * params = [NSMutableDictionary new];
if (appKey) {
params[kQCloudRequestAppkeyKey] = appKey;
}
params[@"pName"] = @"cos";
params[@"sdkVersion"] = QCloudCOSXMLModuleVersion;
params[@"sdkVersionName"] = @(QCloudCOSXMLModuleVersionNumber);
return params;
}
@end

View File

@@ -0,0 +1,125 @@
//
// QCloudCOSXMLService.h
// QCloudCOSXMLService
//
// Created by tencent
//
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudService.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
QCloudCOSXMLService 是对所有接口请求发起的封装通过QCloudCOSXMLService实例来发起网络请求
详情请查看https://cloud.tencent.com/document/product/436/11280
配置QCloudCOSXMLService
1实例化 QCloudServiceConfiguration 对象:
QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];
configuration.appID = @"APPID" //腾讯云账号的 APPID;
2:实例化 QCloudCOSXMLService 对象:
+ (QCloudCOSXMLService*) registerDefaultCOSXMLWithConfiguration
:(QCloudServiceConfiguration*)configuration;
3实例化 QCloudCOSTransferManagerService 对象:
+ (QCloudCOSTransferMangerService*) registerDefaultCOSTransferMangerWithConfiguration
:(QCloudServiceConfiguration*)configuration;
使用步骤:
1实例并初始化好要使用的request
2使用[QCloudCOSXMLService defaultCOSXML] 获取到 QCloudCOSXMLService实例
3调用对应发起请求的方法如get****,post****,put****,delete****,
*/
@interface QCloudCOSXMLService : QCloudService
#pragma hidden super selectors
- (int)performRequest:(QCloudBizHTTPRequest *)httpRequst NS_UNAVAILABLE;
- (int)performRequest:(QCloudBizHTTPRequest *)httpRequst withFinishBlock:(QCloudRequestFinishBlock)block NS_UNAVAILABLE;
#pragma Factory
/**
获取默认的cosxml服务
*/
+ (QCloudCOSXMLService *)defaultCOSXML;
/// 获取指定key的cosxml服务
/// @param key 要获取的cosxml服务对应的key
+ (QCloudCOSXMLService *)cosxmlServiceForKey:(NSString *)key;
#pragma hidden super selectors
/// 注册默认的cosxml服务
/// @param configuration cosxml服务对应的配置信息一旦配置之后无法修改
+ (QCloudCOSXMLService *)registerDefaultCOSXMLWithConfiguration:(QCloudServiceConfiguration *)configuration;
/// 注册特定key的cosxml服务
/// @param configuration cosxml对应的配置信息
/// @param key 该cosxml对应的key
+ (QCloudCOSXMLService *)registerCOSXMLWithConfiguration:(QCloudServiceConfiguration *)configuration withKey:(NSString *)key;
/// 检查是否存在key对应的service
+ (BOOL)hasCosxmlServiceForKey:(NSString *)key;
+ (BOOL)hasServiceForKey:(NSString *)key __attribute__((deprecated("该方法过期请用hasCosxmlServiceForKey:替换")));
/// 删除可以对应的service
+ (void)removeCosxmlServiceWithKey:(NSString *)key;
+ (void)removeCOSXMLWithKey:(NSString *)key __attribute__((deprecated("该方法过期请用removeCosxmlServiceWithKey:替换")));
/**
根据Bukcet, Object来生成可以直接访问的URL。如果您的Bucket是私有读的话那么访问的时候需要带上签名
反之则不需要。
需要注意的是如果通过该接口来生成带签名的URL的话因为签名可能是在服务器生成的该方法是同步方法
可能因为网络请求阻塞,建议不要在主线程里调用。
此外, 传入的Object需要是URLEncode后的结果。
@param bucket 存储桶
@param object 存储对象, 请传入URL Encode后的结果
@param withAuthorization 是否需要签名如果是私有读的Bucket那么该URL需要带上签名才能访问
@return object URL
*/
- (NSString *)getURLWithBucket:(NSString *)bucket
object:(NSString *)object
withAuthorization:(BOOL)withAuthorization
regionName:(NSString *)regionName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,139 @@
//
// COSXML.m
// COSXML
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCOSXMLService.h"
#import "QCloudCOSXMLService+Configuration.h"
#import "QCloudCOSXMLService+Private.h"
QCloudThreadSafeMutableDictionary *QCloudCOSXMLServiceCache() {
static QCloudThreadSafeMutableDictionary *CloudcosxmlService = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CloudcosxmlService = [QCloudThreadSafeMutableDictionary new];
});
return CloudcosxmlService;
}
@implementation QCloudCOSXMLService
static QCloudCOSXMLService *COSXMLService = nil;
+ (QCloudCOSXMLService *)defaultCOSXML {
@synchronized(self) {
if (!COSXMLService) {
@throw [NSException exceptionWithName:QCloudErrorDomain reason:@"您没有配置默认的OCR服务配置请配置之后再调用该方法" userInfo:nil];
}
return COSXMLService;
}
}
+ (QCloudCOSXMLService *)registerDefaultCOSXMLWithConfiguration:(QCloudServiceConfiguration *)configuration {
@synchronized(self) {
if(!COSXMLService){
COSXMLService = [[QCloudCOSXMLService alloc] initWithConfiguration:configuration];
if (!configuration.isCloseShareLog) {
#if TARGET_OS_IOS
if (NSClassFromString(@"QCloudLogManager")) {
Class clazz = NSClassFromString(@"QCloudLogManager");
[clazz performSelector:@selector(sharedInstance)];
}
#endif
}
}
}
return COSXMLService;
}
+ (QCloudCOSXMLService *)cosxmlServiceForKey:(NSString *)key {
QCloudCOSXMLService *cosxmlService = [QCloudCOSXMLServiceCache() objectForKey:key];
if (!cosxmlService) {
@throw [NSException exceptionWithName:QCloudErrorDomain
reason:[NSString stringWithFormat:@"您没有配置Key为%@的OCR服务配置请配置之后再调用该方法", key]
userInfo:nil];
}
return cosxmlService;
}
+ (QCloudCOSXMLService *)registerCOSXMLWithConfiguration:(QCloudServiceConfiguration *)configuration withKey:(NSString *)key;
{
QCloudCOSXMLService *cosxmlService = [QCloudCOSXMLServiceCache() objectForKey:key];
if(!cosxmlService){
cosxmlService = [[QCloudCOSXMLService alloc] initWithConfiguration:configuration];
[QCloudCOSXMLServiceCache() setObject:cosxmlService forKey:key];
}
return cosxmlService;
}
- (NSString *)getURLWithBucket:(NSString *)bucket
object:(NSString *)object
withAuthorization:(BOOL)withAuthorization
regionName:(NSString *)regionName {
NSParameterAssert(bucket);
NSParameterAssert(object);
__block NSMutableString *resultURL = [[NSMutableString alloc] init];
NSString *bucketURL = [[self.configuration.endpoint serverURLWithBucket:bucket appID:self.configuration.appID
regionName:regionName] absoluteString];
[resultURL appendString:bucketURL];
[resultURL appendFormat:@"/%@", object];
if (withAuthorization) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSMutableURLRequest *fakeURLRequest = [[NSMutableURLRequest alloc] init];
[fakeURLRequest setHTTPMethod:@"GET"];
[fakeURLRequest setURL:[NSURL URLWithString:resultURL]];
[self.configuration.signatureProvider signatureWithFields:nil
request:nil
urlRequest:fakeURLRequest
compelete:^(QCloudSignature *signature, NSError *error) {
NSString *sign = signature.signature;
sign = QCloudURLEncodeUTF8(sign);
[resultURL appendFormat:@"?sign=%@", sign];
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
}
return [resultURL copy];
}
+ (BOOL)hasCosxmlServiceForKey:(NSString *)key {
if (nil == [QCloudCOSXMLServiceCache() objectForKey:key]) {
return NO;
} else {
return YES;
}
}
+ (BOOL)hasServiceForKey:(NSString *)key{
return [QCloudCOSXMLService hasCosxmlServiceForKey:key];
}
+ (void)removeCosxmlServiceWithKey:(NSString *)key {
[QCloudCOSXMLServiceCache() removeObjectForKey:key];
}
+ (void)removeCOSXMLWithKey:(NSString *)key{
[self removeCosxmlServiceWithKey:key];
}
@end

View File

@@ -0,0 +1,12 @@
//
// QCloudCOSXMLServiceUtilities.h
// Pods
//
// Created by Dong Zhao on 2017/5/26.
//
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
FOUNDATION_EXTERN NSString *QCloudCOSXMLObjectLocation(QCloudEndPoint *endpoint, NSString *appID, NSString *bucket, NSString *object,
NSString *regionName);

View File

@@ -0,0 +1,15 @@
//
// QCloudCOSXMLServiceUtilities.m
// Pods
//
// Created by Dong Zhao on 2017/5/26.
//
//
#import "QCloudCOSXMLServiceUtilities.h"
#import <QCloudCore/QCloudCore.h>
NSString *QCloudCOSXMLObjectLocation(QCloudEndPoint *endpoint, NSString *appID, NSString *bucket, NSString *object, NSString *regionName) {
NSURL *url = [endpoint serverURLWithBucket:bucket appID:appID regionName:regionName];
return [url URLByAppendingPathComponent:object].absoluteString;
}

View File

@@ -0,0 +1,39 @@
//
// QCloudLogManager.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 2018/10/8.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#if TARGET_OS_IOS
@interface QCloudLogTableViewController : UIViewController
- (instancetype)initWithLog:(NSArray *)logContent;
@end
#endif
/**
QCloudCOSXML 日志管理类
*/
@interface QCloudLogManager : NSObject
/**
是否显示日志信息
*/
@property (nonatomic, assign) BOOL shouldShowLog;
+ (instancetype)sharedInstance;
- (void)showLogs;
/**
已经产生的日志
*/
- (NSArray *)currentLogs;
/**
根据日志路径读取日志
@params path 日志路径
*/
- (NSString *)readLog:(NSString *)path;
- (BOOL)shouldShowLog;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,208 @@
//
// QCloudLogManager.m
// QCloudCOSXML
//
// Created by erichmzhang() on 2018/10/8.
//
#import "QCloudLogManager.h"
#import <QCloudCore/QCloudCore.h>
#if TARGET_OS_IOS
#import <UIKit/UIKit.h>
@interface QCloudLogDetailViewController : UIViewController
- (instancetype)initWithLogPath:(NSString *)logPath LogContent:(NSString *)logContent;
@property (nonatomic, strong) NSString *logContent;
@property (nonatomic, strong) NSString *logPath;
@property (nonatomic, strong) UITextView *textView;
@end
@implementation QCloudLogDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"发送"
style:UIBarButtonItemStylePlain
target:self
action:@selector(onHandleShareLog)];
self.navigationItem.rightBarButtonItem = barButtonItem;
self.textView = [[UITextView alloc] initWithFrame:self.view.frame];
[self.view addSubview:self.textView];
}
- (instancetype)initWithLogPath:(NSString *)logPath LogContent:(NSString *)logContent {
self = [super init];
self.logContent = logContent;
self.logPath = logPath;
return self;
}
- (void)onHandleShareLog {
NSURL *url = [NSURL fileURLWithPath:self.logPath];
NSArray *activityItems = @[ url ];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.textView.text = self.logContent;
}
@end
@interface QCloudLogTableViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSArray *logsDirecotryArray;
@end
@implementation QCloudLogTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.tableView reloadData];
}
- (instancetype)initWithLog:(NSArray *)logContent {
self = [super init];
self.logsDirecotryArray = logContent;
return self;
}
#pragma mark - TableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.logsDirecotryArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuse-cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
cell.textLabel.text = self.logsDirecotryArray[indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// shoud detail view
NSString *logPath = [[QCloudLogger sharedLogger].logDirctoryPath stringByAppendingPathComponent:self.logsDirecotryArray[indexPath.row]];
NSData *logData = [[NSFileManager defaultManager] contentsAtPath:logPath];
NSString *logContent = [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding];
QCloudLogDetailViewController *viewController = [[QCloudLogDetailViewController alloc] initWithLogPath:logPath LogContent:logContent];
[self.navigationController pushViewController:viewController animated:YES];
}
@end
@implementation QCloudLogManager
+ (instancetype)sharedInstance {
static QCloudLogManager *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[QCloudLogManager alloc] init];
});
return instance;
}
- (instancetype)init {
self = [super init];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onHandleDidFinishLaunching:)
name:UIApplicationDidFinishLaunchingNotification
object:nil];
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)onHandleDidFinishLaunching:(NSNotification *)notification {
if (!self.shouldShowLog) {
return;
}
// ios14
if ([UIDevice currentDevice].systemVersion.floatValue >= 10.0) {
if (![[UIPasteboard generalPasteboard] hasStrings]) {
return;
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *currentPasteBoardContent = [UIPasteboard generalPasteboard].string;
if ([currentPasteBoardContent isEqualToString:@"##qcloud-cos-log-ispct##"]) {
[UIPasteboard generalPasteboard].string = @"";
dispatch_async(dispatch_get_main_queue(), ^{
[self handleShowLogs];
});
}
});
}
- (NSArray *)currentLogs {
NSString *directoryPath = [QCloudLogger sharedLogger].logDirctoryPath;
NSArray *content = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:nil];
return content;
}
- (NSString *)readLog:(NSString *)path {
NSData *content = [[NSFileManager defaultManager] contentsAtPath:path];
return [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding];
}
- (void)handleShowLogs {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示"
message:@"确定显示log"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionEnsure = [UIAlertAction actionWithTitle:@"确定"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
[self showLogs];
}];
UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:actionEnsure];
[alertController addAction:actionCancel];
UIViewController *currentViewController = [self currentViewController];
[currentViewController presentViewController:alertController animated:YES completion:nil];
}
- (void)showLogs {
NSArray *currentLogPath = [self currentLogs];
UIViewController *currentViewController = [self currentViewController];
QCloudLogTableViewController *tableViewController = [[QCloudLogTableViewController alloc] initWithLog:currentLogPath];
if ([currentViewController isKindOfClass:UINavigationController.class]) {
[((UINavigationController *)currentViewController) pushViewController:tableViewController animated:YES];
} else {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:tableViewController];
[currentViewController presentViewController:nav animated:YES completion:nil];
}
}
- (UIViewController *)currentViewController {
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
UIViewController *vc = keyWindow.rootViewController;
while (vc.presentedViewController) {
vc = vc.presentedViewController;
if ([vc isKindOfClass:[UINavigationController class]]) {
vc = [(UINavigationController *)vc visibleViewController];
} else if ([vc isKindOfClass:[UITabBarController class]]) {
vc = [(UITabBarController *)vc selectedViewController];
}
}
return vc;
}
@end
#endif

View File

@@ -0,0 +1,16 @@
//
// QCloudRequestData+COSXML.h
// QCloudCOSXML
//
// Created by garenwang on 2025/3/31.
//
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface QCloudRequestData (COSXML)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
//
// QCloudRequestData+COSXML.m
// QCloudCOSXML
//
// Created by garenwang on 2025/3/31.
//
#import "QCloudRequestData+COSXML.h"
@implementation QCloudRequestData (COSXML)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(setValue:forHTTPHeaderField:);
SEL swizzledSelector = @selector(cos_setValue:forHTTPHeaderField:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod
= class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)cos_setValue:(nonnull id)value forHTTPHeaderField:(nonnull NSString *)field {
if ([field.lowercaseString isEqualToString:@"host"] && self.serverURL) {
NSURL * url = [NSURL URLWithString:self.serverURL];
if ([url.host isEqual:value] || !url.host) {
[self cos_setValue:value forHTTPHeaderField:field];
}else{
[self cos_setValue:url.host forHTTPHeaderField:field];
}
}else{
[self cos_setValue:value forHTTPHeaderField:field];
}
}
@end

View File

@@ -0,0 +1,12 @@
//
// QCloudRequestData+COSXMLVersion.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 22/01/2018.
//
#import <QCloudCore/QCloudCore.h>
@interface QCloudRequestData (COSXMLVersion)
@end

View File

@@ -0,0 +1,51 @@
//
#import "QCloudRequestData+COSXMLVersion.h"
#import <QCloudCore/QCloudSDKModuleManager.h>
static NSString *const kCOSXMLModuleName = @"QCloudCOSXML";
@implementation QCloudRequestData (COSXMLVersion)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(loadDefaultHTTPHeaders);
SEL swizzledSelector = @selector(swizzle_loadDefaultHTTPHeaders);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod
= class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)swizzle_loadDefaultHTTPHeaders {
[self swizzle_loadDefaultHTTPHeaders];
static NSDictionary *httpHeaders;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__block NSString *versionString;
NSArray *modules = [[QCloudSDKModuleManager shareInstance] allModules];
[modules enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
QCloudSDKModule *module = obj;
if ([module.name isEqualToString:kCOSXMLModuleName]) {
versionString = module.version;
*stop = YES;
}
}];
NSString *userAgent = [NSString stringWithFormat:@"cos-xml-ios-sdk-v%@", versionString];
httpHeaders = @ { @"Connection" : @"keep-alive", HTTPHeaderUserAgent : userAgent };
});
[httpHeaders enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {
[self setValue:obj forHTTPHeaderField:key];
}];
}
@end

View File

@@ -0,0 +1,15 @@
//
// QCloud Terminal Lab --- service for developers
//
#import <Foundation/Foundation.h>
#ifndef QCloudCOSXMLModuleVersion_h
#define QCloudCOSXMLModuleVersion_h
#define QCloudCOSXMLModuleVersionNumber 605000
//dependency
//
FOUNDATION_EXTERN NSString * const QCloudCOSXMLModuleVersion;
FOUNDATION_EXTERN NSString * const QCloudCOSXMLModuleName;
#endif

View File

@@ -0,0 +1,29 @@
#import "QCloudCOSXMLVersion.h"
NSString * const QCloudCOSXMLModuleVersion = @"6.5.0";
NSString * const QCloudCOSXMLModuleName = @"QCloudCOSXML";
@interface QCloudQCloudCOSXMLLoad : NSObject
@end
@implementation QCloudQCloudCOSXMLLoad
+ (void) load
{
Class cla = NSClassFromString(@"QCloudSDKModuleManager");
if (cla) {
NSMutableDictionary* module = [@{
@"name" : QCloudCOSXMLModuleName,
@"version" : QCloudCOSXMLModuleVersion
} mutableCopy];
NSString* buglyID = @"";
if (buglyID.length > 0) {
module[@"crashID"] = buglyID;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
id share = [cla performSelector:@selector(shareInstance)];
[share performSelector:@selector(registerModuleByJSON:) withObject:module];
#pragma clang diagnostic pop
}
}
@end

View File

@@ -0,0 +1,65 @@
//
// QCloudCOSTransferMangerService.h
// QCloudCOSTransferMangerService
//
// Created by tencent
//
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudService.h>
@class QCloudCOSXMLService;
@class QCloudCOSXMLUploadObjectRequest;
@class QCloudCOSXMLCopyObjectRequest;
@class QCloudCOSXMLDownloadObjectRequest;
NS_ASSUME_NONNULL_BEGIN
@interface QCloudCOSTransferMangerService : QCloudService
@property (nonatomic, strong, readonly) QCloudCOSXMLService *cosService;
#pragma hidden super selectors
- (int)performRequest:(QCloudBizHTTPRequest *)httpRequst NS_UNAVAILABLE;
- (int)performRequest:(QCloudBizHTTPRequest *)httpRequst withFinishBlock:(QCloudRequestFinishBlock)block NS_UNAVAILABLE;
#pragma Factory
+ (QCloudCOSTransferMangerService *)defaultCOSTransferManager;
+ (QCloudCOSTransferMangerService *)costransfermangerServiceForKey:(NSString *)key;
+ (QCloudCOSTransferMangerService *)registerDefaultCOSTransferMangerWithConfiguration:(QCloudServiceConfiguration *)configuration;
+ (QCloudCOSTransferMangerService *)registerCOSTransferMangerWithConfiguration:(QCloudServiceConfiguration *)configuration withKey:(NSString *)key;
- (void)UploadObject:(QCloudCOSXMLUploadObjectRequest *)upload;
- (void)CopyObject:(QCloudCOSXMLCopyObjectRequest *)copy;
- (void)DownloadObject:(QCloudCOSXMLDownloadObjectRequest *)get;
/// 是否注册了该key对应的服务
+ (BOOL)hasTransferMangerServiceForKey:(NSString *)key;
/// 删除key对应的服务
+ (void)removeTransferMangerServiceWithKey:(NSString *)key;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,158 @@
//
// COSTransferManger.m
// COSTransferManger
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCOSTransferMangerService.h"
#import <QCloudCore/QCloudThreadSafeMutableDictionary.h>
#import <QCloudCore/QCloudError.h>
#import "QCloudPutObjectRequest.h"
#import "QCloudInitiateMultipartUploadRequest.h"
#import "QCloudUploadPartRequest.h"
#import "QCloudCompleteMultipartUploadRequest.h"
#import "QCloudCOSXMLService.h"
#import "QCloudCOSXMLUploadObjectRequest.h"
#import "QCloudCOSXMLUploadObjectRequest_Private.h"
#import "QCloudCOSXMLDownloadObjectRequest.h"
#import "QCloudCOSXMLCopyObjectRequest.h"
QCloudThreadSafeMutableDictionary *QCloudCOSTransferMangerServiceCache() {
static QCloudThreadSafeMutableDictionary *CloudcostransfermangerService = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CloudcostransfermangerService = [QCloudThreadSafeMutableDictionary new];
});
return CloudcostransfermangerService;
}
@interface QCloudCOSTransferMangerService ()
@property (nonatomic, strong, readonly) QCloudOperationQueue *uploadFileQueue;
@end
@implementation QCloudCOSTransferMangerService
static QCloudCOSTransferMangerService *COSTransferMangerService = nil;
+ (QCloudCOSTransferMangerService *)defaultCOSTransferManager {
@synchronized(self) {
if (!COSTransferMangerService) {
@throw [NSException exceptionWithName:QCloudErrorDomain reason:@"您没有配置默认的OCR服务配置请配置之后再调用该方法" userInfo:nil];
}
return COSTransferMangerService;
}
}
+ (QCloudCOSTransferMangerService *)registerDefaultCOSTransferMangerWithConfiguration:(QCloudServiceConfiguration *)configuration {
@synchronized(self) {
if(!COSTransferMangerService){
COSTransferMangerService = [[QCloudCOSTransferMangerService alloc] initWithConfiguration:configuration];
}
}
return COSTransferMangerService;
}
+ (QCloudCOSTransferMangerService *)costransfermangerServiceForKey:(NSString *)key {
QCloudCOSTransferMangerService *costransfermangerService = [QCloudCOSTransferMangerServiceCache() objectForKey:key];
if (!costransfermangerService) {
@throw [NSException exceptionWithName:QCloudErrorDomain
reason:[NSString stringWithFormat:@"您没有配置Key为%@的OCR服务配置请配置之后再调用该方法", key]
userInfo:nil];
}
return costransfermangerService;
}
+ (QCloudCOSTransferMangerService *)registerCOSTransferMangerWithConfiguration:(QCloudServiceConfiguration *)configuration withKey:(NSString *)key;
{
QCloudCOSTransferMangerService * costransfermangerService = [QCloudCOSTransferMangerServiceCache() objectForKey:key];
if(!costransfermangerService){
costransfermangerService = [[QCloudCOSTransferMangerService alloc] initWithConfiguration:configuration];
[QCloudCOSTransferMangerServiceCache() setObject:costransfermangerService forKey:key];
}
return costransfermangerService;
}
- (instancetype)initWithConfiguration:(QCloudServiceConfiguration *)configuration {
self = [super initWithConfiguration:configuration];
if (!self) {
return self;
}
_cosService = [[QCloudCOSXMLService alloc] initWithConfiguration:configuration];
_uploadFileQueue = [QCloudOperationQueue new];
_uploadFileQueue.maxConcurrentCountLimit = [QCloudHTTPSessionManager shareClient].maxConcurrentCountLimit;
_uploadFileQueue.customConcurrentCount = [QCloudHTTPSessionManager shareClient].customConcurrentCount;
return self;
}
- (void)UploadObject:(QCloudCOSXMLUploadObjectRequest *)request {
request.transferManager = self;
if (request.networkType != QCloudRequestNetworkNone) {
request.enableQuic = request.networkType == QCloudRequestNetworkQuic;
}else{
request.enableQuic = self.configuration.enableQuic;
}
QCloudLogDebugP(@"Upload",@"UploadObject set transferManager %@", request.transferManager);
QCloudFakeRequestOperation *operation = [[QCloudFakeRequestOperation alloc] initWithRequest:request];
[self.uploadFileQueue addOpreation:operation];
}
- (void)CopyObject:(QCloudCOSXMLCopyObjectRequest *)request {
request.transferManager = self;
if (request.networkType != QCloudRequestNetworkNone) {
request.enableQuic = request.networkType == QCloudRequestNetworkQuic;
}else{
request.enableQuic = self.configuration.enableQuic;
}
QCloudFakeRequestOperation *operation = [[QCloudFakeRequestOperation alloc] initWithRequest:request];
[self.uploadFileQueue addOpreation:operation];
}
- (void)DownloadObject:(QCloudCOSXMLDownloadObjectRequest *)request {
request.transferManager = self;
if (request.networkType != QCloudRequestNetworkNone) {
request.enableQuic = request.networkType == QCloudRequestNetworkQuic;
}else{
request.enableQuic = self.configuration.enableQuic;
}
QCloudFakeRequestOperation *operation = [[QCloudFakeRequestOperation alloc] initWithRequest:request];
[self.uploadFileQueue addOpreation:operation];
}
#pragma mark - UIApplicationDelegate interceptor
+ (BOOL)hasTransferMangerServiceForKey:(NSString *)key {
if (nil == [QCloudCOSTransferMangerServiceCache() objectForKey:key]) {
return NO;
} else {
return YES;
}
}
+ (void)removeTransferMangerServiceWithKey:(NSString *)key {
[QCloudCOSTransferMangerServiceCache() removeObjectForKey:key];
}
@end

View File

@@ -0,0 +1,400 @@
//
// QCloudCOSXMLService+Transfer.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 07/12/2017.
//
#import <Foundation/Foundation.h>
#import "QCloudCOSXMLService.h"
@class QCloudPutObjectRequest;
@class QCloudGetObjectRequest;
@class QCloudInitiateMultipartUploadRequest;
@class QCloudUploadPartRequest;
@class QCloudListMultipartRequest;
@class QCloudCompleteMultipartUploadRequest;
@class QCloudAbortMultipfartUploadRequest;
@class QCloudHeadObjectRequest;
@class QCloudPutObjectCopyRequest;
@class QCloudUploadPartCopyRequest;
@class QCloudPutObjectWatermarkRequest;
NS_ASSUME_NONNULL_BEGIN
@interface QCloudCOSXMLService (Transfer)
/**
简单上传的方法.
简单上传主要适用于在单个请求中上传一个小于 5 GB 大小的对象. 对于大于 5 GB 的对象(或者在高带宽或弱网络环境中)
优先使用分片上传的方式 (https://cloud.tencent.com/document/product/436/14112).
关于简单上传的具体描述,请查看 https://cloud.tencent.com/document/product/436/14113.
关于简单上传接口的具体描述,请查看 https://cloud.tencent.com/document/product/436/7749.
cos iOS SDK 中简单上传请求的方法具体步骤如下:
1. 实例化 QCloudPutObjectRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 PutObject 方法发出请求。
3. 从回调的 finishBlock 中的 outputObject 获取具体内容。
### 示例
@code
QCloudPutObjectRequest* put = [QCloudPutObjectRequest new];
put.object = @"object-name";
put.bucket = @"bucket-12345678";
put.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];
[put setFinishBlock:^(id outputObject, NSError *error) {
//完成回调
if (nil == error) {
//成功
}
}];
[[QCloudCOSXMLService defaultCOSXML] PutObject:put];
*/
- (void)PutObject:(QCloudPutObjectRequest *)request;
/**
下载 COS 对象的方法.
可以直接发起 GET 请求获取 COS 中完整的对象数据, 或者在 GET 请求 中传入 Range 请求头部获取对象的部分内容.
获取COS 对象的同时,对象的元数据将会作为 HTTP 响应头部随对象内容一同返回COS 支持GET
请求时 使用 URL 参数的方式覆盖响应的部分元数据值,例如覆盖 Content-iDisposition 的响应值.
关于获取 COS 对象的具体描述,请查看 https://cloud.tencent.com/document/product/436/14115.
关于获取 COS 对象的接口描述,请查看 https://cloud.tencent.com/document/product/436/7753.
cos iOS SDK 中获取 COS 对象请求的方法具体步骤如下:
1. 实例化 QCloudGetObjectRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 GetObject 方法发出请求。
3. 从回调的 finishBlock 中的 outputObject 获取具体内容。
### 示例
@code
QCloudGetObjectRequest* request = [[QCloudGetObjectRequest alloc] init];
request.bucket = @"bucketName"; //存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
request.object = @"objectName";;
[request setFinishBlock:^(id outputObject, NSError *error) {
//additional actions after finishing
}];
[[QCloudCOSXMLService defaultCOSXML] GetObject:request];
*/
- (void)GetObject:(QCloudGetObjectRequest *)request;
/**
初始化分块上传的方法.
使用分块上传对象时,首先要进行初始化分片上传操作,获取对应分块上传的 uploadId用于后续上传操 作.
分块上传适合于在弱网络或高带宽环境下上传较大的对象.SDK 支持自行切分对象并分别调用uploadPart(UploadPartRequest)
或者uploadPartAsync(UploadPartRequest, CosXmlResultListener)上传各 个分块.
关于分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/14112.
关于初始化分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/7746.
cos iOS SDK 中初始化分块上传请求的方法具体步骤如下:
1. 实例化 QCloudInitiateMultipartUploadRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 InitiateMultipartUpload 方法发出请求。
3. 从回调的 finishBlock 中的获取具体内容。
### 示例
@code
QCloudInitiateMultipartUploadRequest* initrequest = [QCloudInitiateMultipartUploadRequest new];
initrequest.bucket = @"bucketName"; //存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
initrequest.object = @"objectName"
__block QCloudInitiateMultipartUploadResult* initResult;
[initrequest setFinishBlock:^(QCloudInitiateMultipartUploadResult* outputObject, NSError *error) {
initResult = outputObject;
}];
[[QCloudCOSXMLService defaultCOSXML] InitiateMultipartUpload:initrequest];
*/
- (void)InitiateMultipartUpload:(QCloudInitiateMultipartUploadRequest *)request;
/**
上传一个分片块的方法.
使用分块上传时,可将对象切分成一个个分块的方式上传到 COS每个分块上传需要携带分块号partNumber
和 uploadIdinitMultipartUpload(InitMultipartUploadRequest) 每个分块大小为 1 MB 到 5 GB
最后一个分块可以小于 1 MB, 若传入 uploadId 和 partNumber都相同 后传入的块将覆盖之前传入的块,且支持乱序上传.
关于分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/14112.
关于上传一个对象的分块接口的描述,请查看 https://cloud.tencent.com/document/product/436/7750.
cos iOS SDK 中上传一个对象某个分片块请求的方法具体步骤如下:
1. 实例化 QCloudUploadPartRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 UploadPart 方法发出请求。
3. 从回调的 finishBlock 中的 QCloudUploadPartResult 获取具体内容。
### 示例
@code
QCloudUploadPartRequest *partRequest = [QCloudUploadPartRequest new];
partRequest.bucket = @"bucketName";
partRequest.object = @"object";
partRequest.uploadId = @"uploadId"; //标识本次分块上传的 ID
使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId该 ID 不但唯一标识这一分块数据,
也标识了这分块数据在整个文件内的相对位置
partRequest.partNumber = 1; //标识本次分块上传的编号
[partRequest setFinishBlock:^(QCloudUploadPartResult * _Nonnull result, NSError * _Nonnull error) {
}];
[[QCloudCOSXMLService defaultCOSXML]UploadPart:partRequest];
*/
- (void)UploadPart:(QCloudUploadPartRequest *)request;
/**
查询特定分块上传中的已上传的块的方法.
COS 支持查询特定分块上传中的已上传的块, 即可以 罗列出指定 UploadId 所属的所有已上传成功的分块. 因此,基于此可以完成续传功能.
关于分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/14112,
关于查询特定分块上传中的已上传块接口的描述,请查看 https://cloud.tencent.com/document/product/436/7747.
cos iOS SDK 中查询特定分块上传中的已上传块请求的方法具体步骤如下:
1. 实例化 QCloudListMultipartRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 ListMultipart 方法发出请求。
3. 从回调的 finishBlock 中的 QCloudListPartsResult 获取具体内容。
### 示例
@code
QCloudListMultipartRequest* request = [[QCloudListMultipartRequest alloc] init];
request.bucket = @"bucketName"; //存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
request.object = @"objectName";
request.uploadId = @"uploadID";
[request setFinishBlock:^(QCloudListPartsResult * _Nonnull result, NSError * _Nonnull error) {
//additional actions after finishing
}];
[[QCloudCOSXMLService defaultCOSXML] ListMultipart:request];
*/
- (void)ListMultipart:(QCloudListMultipartRequest *)request;
/**
完成整个分块上传的方法.
当使用分块上传uploadPart(UploadPartRequest))完对象的所有块以后,必须调用该
completeMultiUpload(CompleteMultiUploadRequest) 或者
completeMultiUploadAsync(CompleteMultiUploadRequest, CosXmlResultListener)
来完成整个文件的分块上传.且在该请求的 Body 中需要给出每一个块的 PartNumber 和 ETag用来校验块的准 确性.
分块上传适合于在弱网络或高带宽环境下上传较大的对象.SDK 支持自行切分对象并分别调用uploadPart(UploadPartRequest)上传各 个分块.
关于分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/14112.
关于完成整个分片上传接口的描述,请查看 https://cloud.tencent.com/document/product/436/7742.
cos iOS SDK 中完成整个分块上传请求的同步方法具体步骤如下:
1. 实例化 QCloudCompleteMultipartUploadRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 CompleteMultipartUpload 方法发出请求。
3. 从回调的 finishBlock 中的 QCloudUploadObjectResult 获取具体内容。
### 示例
@code
QCloudCompleteMultipartUploadRequest *completeRequst = [QCloudCompleteMultipartUploadRequest new];
completeRequst.bucket = @"bucketName";
completeRequst.object = @"objectName";
completeRequst.uploadId = @"uploadId"; //本次分片上传的UploadID
[completeRequst setFinishBlock:^(QCloudUploadObjectResult * _Nonnull result, NSError * _Nonnull error) {
}];
[[QCloudCOSXMLService defaultCOSXML] CompleteMultipartUpload:completeRequst];
*/
- (void)CompleteMultipartUpload:(QCloudCompleteMultipartUploadRequest *)request;
/**
舍弃一个分块上传且删除已上传的分片块的方法.
COS 支持舍弃一个分块上传且删除已上传的分片块. 注意,已上传但是未终止的分片块会占用存储空间进
而产生存储费用.因此,建议及时完成分块上传 或者舍弃分块上传.
关于分块上传的具体描述,请查看 https://cloud.tencent.com/document/product/436/14112.
关于舍弃一个分块上传且删除已上传的分片块接口的描述,请查看 https://cloud.tencent.com/document/product/436/7740.
cos iOS SDK 中舍弃一个分块上传且删除已上传的分片块请求的方法具体步骤如下:
1. 实例化 QCloudAbortMultipfartUploadRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 AbortMultipfartUpload 方法发出请求。
3. 从回调的 finishBlock 中的 outputObject 获取具体内容。
### 示例
@code
QCloudAbortMultipfartUploadRequest *abortRequest = [QCloudAbortMultipfartUploadRequest new];
abortRequest.bucket = @"bucketName"; ////存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
abortRequest.object = [[QCloudCOSXMLTestUtility sharedInstance]createCanbeDeleteTestObject];
abortRequest.uploadId = @"uploadId";
[abortRequest setFinishBlock:^(id outputObject, NSError *error) {
//additional actions after finishing
}];
[[QCloudCOSXMLService defaultCOSXML]AbortMultipfartUpload:abortRequest];
*/
- (void)AbortMultipfartUpload:(QCloudAbortMultipfartUploadRequest *)request;
/**
获取 COS 对象的元数据信息(meta data)的方法.
获取 COS 对象的元数据信息,需要与 Get 的权限一致.且请求是不返回消息体的.若请求中需要设置
If-Modified-Since 头部,则统一采用 GMT(RFC822) 时间格式例如Tue, 22 Oct 2017 01:35:21 GMT.
如果对象不存在,则 返回404.
关于获取 COS 对象的元数据信息接口的具体描述请查看https://cloud.tencent.com/document/product/436/7745.
cos iOS SDK 中获取 COS 对象的元数据信息的方法具体步骤如下:
1. 实例化 QCloudHeadObjectRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 HeadObject 方法发出请求。
3. 从回调的 finishBlock 中的获取具体内容。
### 示例
@code
QCloudHeadObjectRequest* headerRequest = [QCloudHeadObjectRequest new];
//存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
headerRequest.bucket = @"bucketName";
headerRequest.object = @"objectName";
__block id resultError;
[headerRequest setFinishBlock:^(NSDictionary* result, NSError *error) {
resultError = error;
}];
[[QCloudCOSXMLService defaultCOSXML] HeadObject:headerRequest];
*/
- (void)HeadObject:(QCloudHeadObjectRequest *)request;
/**
简单复制对象的方法.
COS 中复制对象可以完成如下功能:
创建一个新的对象副本.
复制对象并更名,删除原始对象,实现重命名
修改对象的存储类型,在复制时选择相同的源和目标对象键,修改存储类型.
在不同的腾讯云 COS 地域复制对象.
修改对象的元数据,在复制时选择相同的源和目标对象键,并修改其中的元数据,复制对象时,默认将继承原对象的元数据,
但创建日期将会按新对象的时间计算.
当复制的对象小于等于 5 GB 可以使用简单复制https://cloud.tencent.com/document/product/436/14117).
当复制对象超过 5 GB 时必须使用分块复制https://cloud.tencent.com/document/product/436/14118 来实现复制.
关于简单复制接口的具体描述请查看https://cloud.tencent.com/document/product/436/10881.
cos iOS SDK 中简单复制对象的方法具体步骤如下:
1. 实例化 QCloudPutObjectCopyRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 PutObjectCopy 方法发出请求。
3. 从回调的 finishBlock 中的 QCloudCopyObjectResult 获取具体内容。
### 示例
@code
QCloudPutObjectCopyRequest* request = [[QCloudPutObjectCopyRequest alloc] init];
request.bucket = @"bucketName";
request.object = @"objectName";
request.objectCopySource = @"objectCopySource";
[request setFinishBlock:^(QCloudCopyObjectResult* result, NSError* error) {
}];
[[QCloudCOSXMLService defaultCOSXML] PutObjectCopy:request];
*/
- (void)PutObjectCopy:(QCloudPutObjectCopyRequest *)request;
/**
分块复制的方法.
COS 中复制对象可以完成如下功能:
创建一个新的对象副本.
复制对象并更名,删除原始对象,实现重命名
修改对象的存储类型,在复制时选择相同的源和目标对象键,修改存储类型.
在不同的腾讯云 COS 地域复制对象.
修改对象的元数据,在复制时选择相同的源和目标对象键,并修改其中的元数据,复制对象时,默认将继承原对象的元数据,
但创建日期将会按新对象的时间计算.
当复制的对象小于等于 5 GB 可以使用简单复制https://cloud.tencent.com/document/product/436/14117).
当复制对象超过 5 GB 时必须使用分块复制https://cloud.tencent.com/document/product/436/14118 来实现复制.
关于分块复制接口的具体描述请查看https://cloud.tencent.com/document/product/436/8287.
cos iOS SDK 中分块复制的方法具体步骤如下:
1. 实例化 QCloudUploadPartCopyRequest填入需要的参数。
2. 调用 QCloudCOSXMLService 对象中的 UploadPartCopy 方法发出请求。
3. 从回调的 finishBlock 中的 QCloudCopyObjectResult 获取具体内容。
### 示例
@code
QCloudUploadPartCopyRequest* request = [[QCloudUploadPartCopyRequest alloc] init];
request.bucket = @"bucketName";
request.object = @"objectName";
request.source = @"objectCopySource"; // 源文件 URL 路径,可以通过 versionid 子资源指定历史版本
request.uploadID = @"uploadID"; // 在初始化分块上传的响应中会返回一个唯一的描述符upload ID
request.partNumber = 1; // 标志当前分块的序号
[request setFinishBlock:^(QCloudCopyObjectResult* result, NSError* error) {
}];
[[QCloudCOSXMLService defaultCOSXML]UploadPartCopy:request];
*/
- (void)UploadPartCopy:(QCloudUploadPartCopyRequest *)request;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,59 @@
//
// QCloudCOSXMLService+Transfer.m
// QCloudCOSXML
//
// Created by erichmzhang() on 07/12/2017.
//
#import "QCloudCOSXMLService+Transfer.h"
#import "QCloudPutObjectRequest.h"
#import "QCloudGetObjectRequest.h"
#import "QCloudInitiateMultipartUploadRequest.h"
#import "QCloudUploadPartRequest.h"
#import "QCloudCompleteMultipartUploadRequest.h"
#import "QCloudAbortMultipfartUploadRequest.h"
#import "QCloudListMultipartRequest.h"
#import "QCloudHeadObjectRequest.h"
#import "QCloudUploadPartCopyRequest.h"
#import "QCloudPutObjectCopyRequest.h"
@implementation QCloudCOSXMLService (Transfer)
- (void)PutObject:(QCloudPutObjectRequest *)request {
[super performRequest:request];
}
- (void)GetObject:(QCloudGetObjectRequest *)request {
[super performRequest:request];
}
- (void)InitiateMultipartUpload:(QCloudInitiateMultipartUploadRequest *)request {
[super performRequest:request];
}
- (void)UploadPart:(QCloudUploadPartRequest *)request {
[super performRequest:request];
}
- (void)CompleteMultipartUpload:(QCloudCompleteMultipartUploadRequest *)request {
[super performRequest:request];
}
- (void)AbortMultipfartUpload:(QCloudAbortMultipfartUploadRequest *)request {
[super performRequest:request];
}
- (void)ListMultipart:(QCloudListMultipartRequest *)request {
[super performRequest:request];
}
- (void)HeadObject:(QCloudHeadObjectRequest *)request {
[super performRequest:request];
}
- (void)PutObjectCopy:(QCloudPutObjectCopyRequest *)request {
[super performRequest:request];
}
- (void)UploadPartCopy:(QCloudUploadPartCopyRequest *)request {
[super performRequest:request];
}
@end

View File

@@ -0,0 +1,29 @@
//
// QCloudCOSXMLTransfe.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 08/12/2017.
//
#ifndef QCloudCOSXMLTransfe_h
#define QCloudCOSXMLTransfe_h
#import "QCloudCOSXMLEndPoint.h"
#import "QCloudCOSXMLService+Transfer.h"
#import "QCloudCOSTransferMangerService.h"
#import "QCloudCOSXMLUploadObjectRequest.h"
#import "QCloudCOSXMLUploadObjectRequest_Private.h"
#import "QCloudPutObjectRequest.h"
#import "QCloudGetObjectRequest.h"
#import "QCloudInitiateMultipartUploadRequest.h"
#import "QCloudUploadPartRequest.h"
#import "QCloudCompleteMultipartUploadRequest.h"
#import "QCloudAbortMultipfartUploadRequest.h"
#import "QCloudListMultipartRequest.h"
#import "QCloudHeadObjectRequest.h"
#import "QCloudPutObjectCopyRequest.h"
#import "QCloudUploadPartCopyRequest.h"
#endif /* QCloudCOSXMLTransfe_h */

View File

@@ -0,0 +1,56 @@
//
// COSStorageClass.h
// COSStorageClass
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
存储类型枚举
*/
typedef NS_ENUM(NSInteger, QCloudCOSStorageClass) {
QCloudCOSStorageStandard = 0,
QCloudCOSStorageStandardIA = 1,
QCloudCOSStorageARCHIVE = 2,
QCloudCOSStorageMAZ_Standard = 3,
QCloudCOSStorageMAZ_StandardIA = 4,
//智能分层
QCloudCOSStorageINTELLIGENT_TIERING = 5,
//多AZ智能分层
QCloudCOSStorageMAZ_INTELLIGENT_TIERING = 6,
//深度归档
QCloudCOSStorageDEEP_ARCHIVE = 7,
QCloudCOSStorageCOLD = 8,
QCloudCOSStorageMAZ_COLD = 9,
};
FOUNDATION_EXTERN QCloudCOSStorageClass QCloudCOSStorageClassDumpFromString(NSString *key);
FOUNDATION_EXTERN NSString *QCloudCOSStorageClassTransferToString(QCloudCOSStorageClass type);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,71 @@
//
// COSStorageClass.h
// COSStorageClass
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
#import "QCloudCOSStorageClassEnum.h"
QCloudCOSStorageClass QCloudCOSStorageClassDumpFromString(NSString *key) {
if (NO) {
} else if ([key isEqualToString:@"STANDARD"]) {
return QCloudCOSStorageStandard;
} else if ([key isEqualToString:@"STANDARD_IA"]) {
return QCloudCOSStorageStandardIA;
} else if ([key isEqualToString:@"ARCHIVE"]) {
return QCloudCOSStorageARCHIVE;
} else if ([key isEqualToString:@"MAZ_STANDARD"]) {
return QCloudCOSStorageMAZ_Standard;
} else if ([key isEqualToString:@"MAZ_STANDARD_IA"]) {
return QCloudCOSStorageMAZ_StandardIA;
} else if ([key isEqualToString:@"INTELLIGENT_TIERING"]) {
return QCloudCOSStorageINTELLIGENT_TIERING;
} else if ([key isEqualToString:@"MAZ_INTELLIGENT_TIERING"]) {
return QCloudCOSStorageMAZ_INTELLIGENT_TIERING;
} else if ([key isEqualToString:@"DEEP_ARCHIVE"]) {
return QCloudCOSStorageDEEP_ARCHIVE;
} else if ([key isEqualToString:@"COLD"]) {
return QCloudCOSStorageCOLD;
} else if ([key isEqualToString:@"MAZ_COLD"]) {
return QCloudCOSStorageMAZ_COLD;
}
return 0;
}
NSString *QCloudCOSStorageClassTransferToString(QCloudCOSStorageClass type) {
switch (type) {
case QCloudCOSStorageStandard: {
return @"STANDARD";
}
case QCloudCOSStorageStandardIA: {
return @"STANDARD_IA";
}
case QCloudCOSStorageARCHIVE: {
return @"ARCHIVE";
}
case QCloudCOSStorageMAZ_Standard: {
return @"MAZ_STANDARD";
}
case QCloudCOSStorageMAZ_StandardIA: {
return @"MAZ_STANDARD_IA";
}
case QCloudCOSStorageINTELLIGENT_TIERING: {
return @"INTELLIGENT_TIERING";
}
case QCloudCOSStorageMAZ_INTELLIGENT_TIERING: {
return @"MAZ_INTELLIGENT_TIERING";
}
case QCloudCOSStorageDEEP_ARCHIVE: {
return @"DEEP_ARCHIVE";
}
case QCloudCOSStorageCOLD: {
return @"COLD";
}
case QCloudCOSStorageMAZ_COLD: {
return @"MAZ_COLD";
}
default:
return nil;
}
}

View File

@@ -0,0 +1,46 @@
//
// QCloudCompleteMultipartUploadInfo.h
// QCloudCompleteMultipartUploadInfo
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudMultipartInfo.h"
NS_ASSUME_NONNULL_BEGIN
/**
完成分片上传的信息
*/
@interface QCloudCompleteMultipartUploadInfo : NSObject
/**
用来说明本次分块上传中每个块的信息
*/
@property (strong, nonatomic) NSArray<QCloudMultipartInfo *> *parts;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,82 @@
//
// QCloudCompleteMultipartUploadInfo.m
// QCloudCompleteMultipartUploadInfo
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCompleteMultipartUploadInfo.h"
#import "QCloudMultipartInfo.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudCompleteMultipartUploadInfo
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"parts" : [QCloudMultipartInfo class],
};
}
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"parts" : @"Part",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
NSArray *transformArrayKeypaths = @[
@"Part",
];
for (NSString *keyPath in transformArrayKeypaths) {
id object = [dic valueForKeyPath:keyPath];
if (!object) {
continue;
}
if ([object isKindOfClass:[NSNull class]]) {
continue;
}
if (![object isKindOfClass:[NSArray class]]) {
[transfromDic setValue:@[ object ] forKeyPath:keyPath];
}
}
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,54 @@
//
// QCloudCopyObjectResult.h
// QCloudCopyObjectResult
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
文件复制完成返回结果
*/
@interface QCloudCopyObjectResult : NSObject
/*
文件的 SHA-1 算法校验值。ETag 的值可以用于检查 Object 的内容是否发生变化。
*/
@property (strong, nonatomic) NSString *eTag;
/*
文件的最后修改时间GMT格式
*/
@property (strong, nonatomic) NSString *lastModified;
/**
对象对应的Version ID在开启了多版本的情况才有
*/
@property (strong, nonatomic) NSString *versionID;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,60 @@
//
// QCloudCopyObjectResult.m
// QCloudCopyObjectResult
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCopyObjectResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudCopyObjectResult
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"eTag" : @"ETag",
@"lastModified" : @"LastModified",
@"versionID" : @"x-cos-version-id",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,53 @@
//
// QCloudInitiateMultipartUploadResult.h
// QCloudInitiateMultipartUploadResult
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
初始化分块上传结果信息
*/
@interface QCloudInitiateMultipartUploadResult : NSObject
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
对象的名称
*/
@property (strong, nonatomic) NSString *key;
/**
在后续上传中使用的ID
*/
@property (strong, nonatomic) NSString *uploadId;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,60 @@
//
// QCloudInitiateMultipartUploadResult.m
// QCloudInitiateMultipartUploadResult
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudInitiateMultipartUploadResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudInitiateMultipartUploadResult
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"bucket" : @"Bucket",
@"key" : @"Key",
@"uploadId" : @"UploadId",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,93 @@
//
// QCloudListPartsResult.h
// QCloudListPartsResult
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCOSStorageClassEnum.h"
#import "QCloudMultipartUploadInitiator.h"
#import "QCloudMultipartUploadOwner.h"
#import "QCloudMultipartUploadPart.h"
NS_ASSUME_NONNULL_BEGIN
/**
分块上传中已经上传的数据块
*/
@interface QCloudListPartsResult : NSObject
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
规定返回值的编码格式
*/
@property (strong, nonatomic) NSString *encodingType;
/**
对象的名称
*/
@property (strong, nonatomic) NSString *key;
/**
标识本次分块上传的uploadId
*/
@property (strong, nonatomic) NSString *uploadId;
/**
用来表示这些分块的存储级别
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始
*/
@property (strong, nonatomic) NSString *partNumberMarker;
/**
假如返回条目被截断,则返回 NextMarker 就是下一个条目的起点
*/
@property (strong, nonatomic) NSString *nextNumberMarker;
/**
单次返回的最大条目数
*/
@property (strong, nonatomic) NSString *maxParts;
/**
返回条目是否被截断
*/
@property (assign, nonatomic) BOOL isTruncated;
/**
用来标识本次上传发起者的信息
*/
@property (strong, nonatomic) QCloudMultipartUploadInitiator *initiator;
/**
用来标识这些分块所有者的信息
*/
@property (strong, nonatomic) QCloudMultipartUploadOwner *owner;
/**
用来表示每一个块的信息
*/
@property (strong, nonatomic) NSArray<QCloudMultipartUploadPart *> *parts;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,108 @@
//
// QCloudListPartsResult.m
// QCloudListPartsResult
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudListPartsResult.h"
#import "QCloudMultipartUploadInitiator.h"
#import "QCloudMultipartUploadOwner.h"
#import "QCloudMultipartUploadPart.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudListPartsResult
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"parts" : [QCloudMultipartUploadPart class],
};
}
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"bucket" : @"Bucket",
@"encodingType" : @"Encoding-type",
@"key" : @"Key",
@"uploadId" : @"UploadID",
@"storageClass" : @"StorageClass",
@"partNumberMarker" : @"PartNumberMarker",
@"nextNumberMarker" : @"NextPartNumberMarker",
@"maxParts" : @"MaxParts",
@"isTruncated" : @"IsTruncated",
@"initiator" : @"Initiator",
@"owner" : @"Owner",
@"parts" : @"Part",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
NSNumber *storageClass = dic[@"StorageClass"];
if (storageClass) {
NSString *value = QCloudCOSStorageClassTransferToString([storageClass intValue]);
if (value) {
dic[@"StorageClass"] = value;
}
}
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
NSArray *transformArrayKeypaths = @[
@"Part",
];
for (NSString *keyPath in transformArrayKeypaths) {
id object = [dic valueForKeyPath:keyPath];
if (!object) {
continue;
}
if ([object isKindOfClass:[NSNull class]]) {
continue;
}
if (![object isKindOfClass:[NSArray class]]) {
[transfromDic setValue:@[ object ] forKeyPath:keyPath];
}
}
NSString *storageClass = transfromDic[@"StorageClass"];
if (storageClass && [storageClass isKindOfClass:[NSString class]] && storageClass.length > 0) {
NSInteger value = QCloudCOSStorageClassDumpFromString(storageClass);
transfromDic[@"StorageClass"] = @(value);
}
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,49 @@
//
// QCloudMultipartInfo.h
// QCloudMultipartInfo
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
分块上传中每一个数据块信息
*/
@interface QCloudMultipartInfo : NSObject
/**
块编号
*/
@property (strong, nonatomic) NSString *partNumber;
/**
每个块文件的MD5算法校验值
*/
@property (strong, nonatomic) NSString *eTag;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,59 @@
//
// QCloudMultipartInfo.m
// QCloudMultipartInfo
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudMultipartInfo.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudMultipartInfo
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"partNumber" : @"PartNumber",
@"eTag" : @"ETag",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
//
// QCloudMultipartUploadInitiator.h
// QCloudMultipartUploadInitiator
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
用来表示这些分块所有者的信息。
*/
@interface QCloudMultipartUploadInitiator : NSObject
/**
创建者的一个唯一标识
*/
@property (strong, nonatomic) NSString *identifier;
/**
创建者的用户名描述。
*/
@property (strong, nonatomic) NSString *displayName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,59 @@
//
// QCloudMultipartUploadInitiator.m
// QCloudMultipartUploadInitiator
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudMultipartUploadInitiator.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudMultipartUploadInitiator
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"identifier" : @"ID",
@"displayName" : @"DisplayName",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
//
// QCloudMultipartUploadOwner.h
// QCloudMultipartUploadOwner
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
用来表示这些分块所有者的信息。
*/
@interface QCloudMultipartUploadOwner : NSObject
/**
创建者的一个唯一标识
*/
@property (strong, nonatomic) NSString *identifier;
/**
创建者的用户名描述。
*/
@property (strong, nonatomic) NSString *displayName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,59 @@
//
// QCloudMultipartUploadOwner.m
// QCloudMultipartUploadOwner
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudMultipartUploadOwner.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudMultipartUploadOwner
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"identifier" : @"ID",
@"displayName" : @"DisplayName",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,57 @@
//
// QCloudMultipartUploadPart.h
// QCloudMultipartUploadPart
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
查询特定上传分块中已上传的分块返回结果的元数据信息
*/
@interface QCloudMultipartUploadPart : NSObject
/**
块的编号
*/
@property (strong, nonatomic) NSString *partNumber;
/**
块的最后修改时间
*/
@property (strong, nonatomic) NSString *lastModified;
/**
对象的SHA-1算法校验值
*/
@property (strong, nonatomic) NSString *eTag;
/**
块大小单位byte
*/
@property (assign, nonatomic) int64_t size;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,61 @@
//
// QCloudMultipartUploadPart.m
// QCloudMultipartUploadPart
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudMultipartUploadPart.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudMultipartUploadPart
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"partNumber" : @"PartNumber",
@"lastModified" : @"LastModified",
@"eTag" : @"ETag",
@"size" : @"Size",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,89 @@
//
// QCloudUploadObjectResult.h
// QCloudUploadObjectResult
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface QCloudUploadCallbackError : NSObject
@property (strong, nonatomic) NSString *Code;
@property (strong, nonatomic) NSString *Message;
@end
@interface QCloudUploadCallbackResult : NSObject
@property (strong, nonatomic) NSString *Status;
@property (strong, nonatomic) QCloudUploadCallbackError *Error;
@property (strong, nonatomic) NSString *CallbackBody;
@end
/**
完成分块上传返回结果信息
*/
@interface QCloudUploadObjectResult : NSObject
/**
创建对象的外网访问域名
*/
@property (strong, nonatomic) NSString *location;
/**
分快上传的目标存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
对象名
*/
@property (strong, nonatomic) NSString *key;
/**
合并后文件的MD5算法校验值
*/
@property (strong, nonatomic) NSString *eTag;
/**
对象对应的Version ID在开启了多版本的情况才有
*/
@property (strong, nonatomic) NSString *versionID;
/**
文件大小
*/
@property (assign, nonatomic) NSInteger size;
@property (strong, nonatomic) QCloudUploadCallbackResult *CallbackResult;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,79 @@
//
// QCloudUploadObjectResult.m
// QCloudUploadObjectResult
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudUploadObjectResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudUploadCallbackError
@end
@implementation QCloudUploadCallbackResult
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"Error" : [QCloudUploadCallbackError class],
};
}
@end
@implementation QCloudUploadObjectResult
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"CallbackResult" : [QCloudUploadCallbackResult class],
};
}
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"location" : @"Location",
@"bucket" : @"Bucket",
@"key" : @"Key",
@"eTag" : @"ETag",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,45 @@
//
// QCloudUploadPartResult.h
// QCloudUploadPartResult
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
完成一个分块上传返回结果
*/
@interface QCloudUploadPartResult : NSObject
/**
文件的 etag
*/
@property (strong, nonatomic) NSString *eTag;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,58 @@
//
// QCloudUploadPartResult.m
// QCloudUploadPartResult
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudUploadPartResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudUploadPartResult
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"eTag" : @"Etag",
};
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic {
if (!dic) {
return dic;
}
NSMutableDictionary *transfromDic = [NSMutableDictionary dictionaryWithDictionary:dic];
return transfromDic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,75 @@
//
// AbortMultipfartUpload.h
// AbortMultipfartUpload
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudBizHTTPRequest.h>
NS_ASSUME_NONNULL_BEGIN
/**
舍弃一个分块上传且删除已上传的分片块的方法.
### 功能描述
COS 支持舍弃一个分块上传且删除已上传的分片块. 注意,已上传但是未终止的分片块会占用存储空间进
而产生存储费用.因此,建议及时完成分块上传 或者舍弃分块上传.
关于舍弃一个分块上传且删除已上传的分片块接口的描述,请查看 https://cloud.tencent.com/document/product/436/7740.
### 示例
@code
QCloudAbortMultipfartUploadRequest *abortRequest = [QCloudAbortMultipfartUploadRequest new];
abortRequest.bucket = @"bucketName"; //存储桶名称(cos v5 的 bucket格式为xxx-appid, 如 test-1253960454)
abortRequest.object = [[QCloudCOSXMLTestUtility sharedInstance]createCanbeDeleteTestObject];
abortRequest.uploadId = @"uploadId";
[abortRequest setFinishBlock:^(id outputObject, NSError *error) {
//additional actions after finishing
}];
[[QCloudCOSXMLService defaultCOSXML]AbortMultipfartUpload:abortRequest];
*/
@interface QCloudAbortMultipfartUploadRequest : QCloudBizHTTPRequest
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
本次分片上传的UploadId
*/
@property (strong, nonatomic) NSString *uploadId;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,134 @@
//
// AbortMultipfartUpload.m
// AbortMultipfartUpload
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudAbortMultipfartUploadRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudAbortMultipfartUploadRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithURLEncodeParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"delete";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (!self.uploadId || ([self.uploadId isKindOfClass:NSString.class] && ((NSString *)self.uploadId).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[uploadId] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setParameter:self.uploadId withKey:@"UploadId"];
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
return YES;
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:UploadPart"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,95 @@
//
// AppendObject.h
// AppendObject
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗ ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║ ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _ __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \ '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/ | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/ \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCOSStorageClassEnum.h"
NS_ASSUME_NONNULL_BEGIN
/**
功能描述:
APPEND Object 接口请求可以将一个对象以分块追加的方式上传至指定存储桶中。对象首次使用 APPEND Object 接口上传时,该对象的属性自动为 appendable ,使用其他接口上传时则属性自动为 normal (如果该对象已存在则属性会被覆盖为 normal可以使用 GET Object 或 HEAD Object 接口获取 x-cos-object-type 响应头来判断对象属性。对象属性为 appendable 时才能使用本接口追加上传。
追加上传的对象每个分块大小默认最大为5GB无最小限制同时通过追加方式产生的对象大小不得超过5GB。如果 Position 的值和当前对象的长度不致COS 将返回409错误。如果追加一个 normal 属性的文件COS 将返回409 ObjectNotAppendable。
*/
@interface QCloudAppendObjectRequest <BodyType> : QCloudBizHTTPRequest
@property (nonatomic, strong) BodyType body;
/**
位置
*/
@property (assign, nonatomic) int64_t position;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
RFC 2616 中定义的缓存策略,将作为 Object 元数据返回
*/
@property (strong, nonatomic) NSString *cacheControl;
/**
RFC 2616 中定义的文件名称,将作为 Object 元数据返回
*/
@property (strong, nonatomic) NSString *contentDisposition;
/**
当使用 Expect: 100-continue 时,在收到服务端确认后,才会发送请求内容
*/
@property (strong, nonatomic) NSString *expect;
/**
RFC 2616 中定义的过期时间,将作为 Object 元数据返回
*/
@property (strong, nonatomic) NSString *expires;
@property (strong, nonatomic) NSString *contentSHA1;
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式x-cos-grant-read: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者写的权限。格式x-cos-grant-write: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantWrite;
/**
赋予被授权者读写权限。格式x-cos-grant-full-control: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/<OwnerUin>:uin/<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantFullControl;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,142 @@
//
// AppendObject.m
// AppendObject
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _ __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \ '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/ | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/ \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudAppendObjectRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudAppendObjectRequest
- (void) dealloc
{
}
- (instancetype) init
{
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void) configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer
{
NSArray* customRequestSerilizers = @[
QCloudURLFuseURIMethodASURLParamters,
QCloudURLFuseWithURLEncodeParamters,
];
NSArray* responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseAppendHeadersSerializerBlock,
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"post";
}
- (BOOL) buildRequestData:(NSError *__autoreleasing *)error
{
if (![super buildRequestData:error]) {
return NO;
}
[self.requestData setNumberParamter:@(self.position) withKey:@"position"];
self.requestData.URIMethod = @"append";
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString*)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid message:[NSString stringWithFormat:@"paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString*)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid message:[NSString stringWithFormat:@"paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (self.cacheControl) {
[self.requestData setValue:self.cacheControl forHTTPHeaderField:@"Cache-Control"];
}
if (self.contentDisposition) {
[self.requestData setValue:self.contentDisposition forHTTPHeaderField:@"Content-Disposition"];
}
if (self.expect) {
[self.requestData setValue:self.expect forHTTPHeaderField:@"Expect"];
}
if (self.expires) {
[self.requestData setValue:self.expires forHTTPHeaderField:@"Expires"];
}
if (self.contentSHA1) {
[self.requestData setValue:self.contentSHA1 forHTTPHeaderField:@"x-cos-content-sha1"];
}
[self.requestData setValue:QCloudCOSStorageClassTransferToString(self.storageClass) forHTTPHeaderField:@"x-cos-storage-class"];
if (self.accessControlList) {
[self.requestData setValue:self.accessControlList forHTTPHeaderField:@"x-cos-acl"];
}
if (self.grantRead) {
[self.requestData setValue:self.grantRead forHTTPHeaderField:@"x-cos-grant-read"];
}
if (self.grantWrite) {
[self.requestData setValue:self.grantWrite forHTTPHeaderField:@"x-cos-grant-write"];
}
if (self.grantFullControl) {
[self.requestData setValue:self.grantFullControl forHTTPHeaderField:@"x-cos-grant-full-control"];
}
NSMutableArray* __pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if(self.object) [__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
self.requestData.directBody = self.body;
return YES;
}
- (QCloudSignatureFields*) signatureFields
{
QCloudSignatureFields* fileds = [QCloudSignatureFields new];
return fileds;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,156 @@
//
// QCloudCOSXMLCopyObjectRequest.h
// QCloudCOSXML
//
// Created by erichmzhang(张恒铭) on 16/11/2017.
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCOSStorageClassEnum.h"
#import "QCloudCopyObjectResult.h"
#import "QCloudCOSTransferMangerService.h"
NS_ASSUME_NONNULL_BEGIN
typedef void (^CopyProgressBlock)(int64_t partsSent, int64_t totalPartsExpectedToSent);
typedef void (^RequestsMetricArrayBlock)(NSMutableArray *_Nullable requstMetricArray);
/**
复制对象
1先初始化一个 QCloudCOSXMLCopyObjectRequest 对象
2然后调用 QCloudCOSTransferMangerService 的 CopyObject 方法即可。
注意对于比较大的文件,将会使用分块复制的方式进行复制。这个过程对于用户是没有感知的。
### 示例
@code
QCloudCOSXMLCopyObjectRequest* request = [[QCloudCOSXMLCopyObjectRequest alloc] init];
request.bucket = @"examplebucket-1250000000";//目的 \<BucketName-APPID>,需要是公有读或者在当前账号有权限
request.object = @"exampleobject";//目的文件名称
//文件来源 \<BucketName-APPID>,需要是公有读或者在当前账号有权限
request.sourceBucket = @"sourcebucket-1250000000";
request.sourceObject = @"sourceObject";//源文件名称
request.sourceAPPID = @"1250000000";//源文件的 APPID
request.sourceRegion= @"COS_REGION";//来源的地域
[request setFinishBlock:^(QCloudCopyObjectResult* result, NSError* error) {
//可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息
}];
//注意如果是跨地域复制,这里使用的 transferManager 所在的 region 必须为目标桶所在的 region
[[QCloudCOSTransferMangerService defaultCOSTransferManager] CopyObject:request];
*/
@interface QCloudCOSXMLCopyObjectRequest : QCloudAbstractRequest
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
复制的源文件所在Bucket
*/
@property (nonatomic, copy) NSString *sourceBucket;
/**
复制的源文件的对象名key
*/
@property (nonatomic, copy) NSString *sourceObject;
/**
复制的源文件的appID
*/
@property (nonatomic, copy) NSString *sourceAPPID;
/**
复制的源文件所在的区域。
*/
@property (nonatomic, copy) NSString *sourceRegion;
/**
源文件的版本ID
*/
@property (nonatomic, copy) NSString *sourceObjectVersionID;
/**
是否拷贝元数据枚举值Copy, Replaced默认值 Copy。假如标记为 Copy忽略 Header
中的用户元数据信息直接复制;假如标记为 Replaced按 Header 信息修改元数据。当目标路径和原路径一致
,即用户试图修改元数据时,必须为 Replaced
*/
@property (strong, nonatomic) NSString *metadataDirective;
/**
当 Object 在指定时间后被修改,则执行操作,否则返回 412。可与 x-cos-copy-source-If-None-Match
一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfModifiedSince;
/**
当 Object 在指定时间后未被修改,则执行操作,否则返回 412。可与 x-cos-copy-source-If-Match
一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfUnmodifiedSince;
/**
当 Object 的 Etag 和给定一致时,则执行操作,否则返回 412。可与x-cos-copy-source-If-Unmodified-Since
一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfMatch;
/**
当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。可与 x-cos-copy-source-If-Modified-Since
一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfNoneMatch;
/**
Object 的存储级别
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者写的权限。格式id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantWrite;
/**
赋予被授权者读写权限。格式: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantFullControl;
@property (nonatomic, weak) QCloudCOSTransferMangerService *transferManager;
/*
在进行HTTP请求的时候可以通过设置该参数来设置自定义的一些头部信息。
通常情况下携带特定的额外HTTP头部可以使用某项功能如果是这类需求可以通过设置该属性来实现。
*/
@property (strong, nonatomic) NSMutableDictionary *customHeaders;
@property (strong, nonatomic) NSString *regionName;
/**
在对大文件进行复制的过程中,会通过分片的方式进行复制。从该进度回调里可以获取当前已经复制了多少分片。
@param copyProgressBlock 进度回调block
*/
- (void)setCopyProgressBlock:(void (^)(int64_t partsSent, int64_t totalPartsExpectedToSent))copyProgressBlock;
@property (nonatomic, copy) RequestsMetricArrayBlock requstsMetricArrayBlock;
/**
Copy操作完成后的回调
@param QCloudRequestFinishBlock 完成回调
*/
- (void)setFinishBlock:(void (^_Nullable)(QCloudCopyObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,358 @@
//
// QCloudCOSXMLCopyObjectRequest.m
// QCloudCOSXML
//
// Created by erichmzhang() on 16/11/2017.
//
#import "QCloudCOSXMLCopyObjectRequest.h"
#import "QCloudCOSXMLService.h"
#import "QCloudPutObjectRequest.h"
#import "QCloudCOSXMLService+Transfer.h"
#import "QCloudMultipartInfo.h"
#import "QCloudCOSXMLTransfer.h"
#import "QCloudCompleteMultipartUploadRequest.h"
#import "QCloudCompleteMultipartUploadInfo.h"
#import "QCloudHeadObjectRequest.h"
#import <QCloudCore/QCloudURLHelper.h>
static NSString *const kTempServiceKey = @"tempServiceKey";
static NSString *const kContentLengthKey = @"Content-Length";
static NSString *const kLastModifiedKey = @"Last-Modified";
static const int64_t kMultipartThreshold = 5242880;
static const int64_t kCopySliceLength = 5242880;
@interface QCloudCOSXMLCopyObjectRequest ()
@property (nonatomic, assign) int64_t fileSize;
@property (nonatomic, assign) int64_t sliceCount;
@property (nonatomic, strong) dispatch_source_t dispatchSource;
@property (nonatomic, copy) NSString *uploadID;
@property (nonatomic, strong) NSMutableArray *uploadParts;
@property (nonatomic, copy) NSString *lastModified;
@property (nonatomic, copy) CopyProgressBlock copyProgressBlock;
@property (strong, nonatomic) NSMutableArray *requstMetricArray;
@end
@implementation QCloudCOSXMLCopyObjectRequest
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
_customHeaders = [NSMutableDictionary dictionary];
_requstMetricArray = [NSMutableArray array];
_fileSize = 0;
_sliceCount = 0;
return self;
}
- (void)fakeStart {
QCloudHeadObjectRequest *headObjectRequest = [[QCloudHeadObjectRequest alloc] init];
NSMutableDictionary *customHeaders = [NSMutableDictionary dictionary];
if (self.customHeaders) {
if ([self.customHeaders objectForKey:@"x-cos-copy-source-server-side-encryption-customer-algorithm"]) {
customHeaders[@"x-cos-server-side-encryption-customer-algorithm"]
= self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-algorithm"];
}
if ([self.customHeaders objectForKey:@"x-cos-copy-source-server-side-encryption-customer-key"]) {
customHeaders[@"x-cos-server-side-encryption-customer-key"]
= self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-key"];
}
if ([self.customHeaders objectForKey:@"x-cos-copy-source-server-side-encryption-customer-key-MD5"]) {
customHeaders[@"x-cos-server-side-encryption-customer-key-MD5"]
= self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-key-MD5"];
}
}
headObjectRequest.customHeaders = [customHeaders mutableCopy];
headObjectRequest.bucket = self.sourceBucket;
headObjectRequest.payload = self.payload;
headObjectRequest.regionName = self.sourceRegion;
headObjectRequest.priority = self.priority;
headObjectRequest.enableQuic = self.enableQuic;
headObjectRequest.endpoint = self.endpoint;
headObjectRequest.networkType = self.networkType;
headObjectRequest.object = self.sourceObject;
headObjectRequest.ifModifiedSince = self.objectCopyIfModifiedSince;
__weak typeof(headObjectRequest) weakRequest = headObjectRequest;
__weak typeof(self) weakSelf = self;
[headObjectRequest setFinishBlock:^(id outputObject, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (error) {
if (self.finishBlock) {
self.finishBlock(nil, error);
}
} else {
NSDictionary *resultDictionray = (NSDictionary *)outputObject;
int64_t fileSize = [resultDictionray[kContentLengthKey] longLongValue];
weakSelf.lastModified = resultDictionray[kLastModifiedKey];
if (fileSize > kMultipartThreshold) {
weakSelf.sliceCount = fileSize / kCopySliceLength;
if (fileSize % kCopySliceLength != 0) {
weakSelf.sliceCount++;
}
weakSelf.fileSize = fileSize;
[weakSelf multipleCopy];
} else {
[weakSelf simpleCopy];
}
}
}];
QCloudCOSXMLService *service = [self tempService];
[service HeadObject:headObjectRequest];
}
- (void)simpleCopy {
QCloudPutObjectCopyRequest *request = [[QCloudPutObjectCopyRequest alloc] init];
request.priority = self.priority;
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
request.customHeaders = [self.customHeaders mutableCopy];
request.regionName = self.regionName;
request.bucket = self.bucket;
request.object = self.object;
request.objectCopyIfMatch = self.objectCopyIfMatch;
request.objectCopyIfNoneMatch = self.objectCopyIfNoneMatch;
request.objectCopyIfModifiedSince = self.objectCopyIfModifiedSince;
request.objectCopyIfUnmodifiedSince = self.objectCopyIfUnmodifiedSince;
request.accessControlList = self.accessControlList;
request.grantRead = self.grantRead;
request.grantWrite = self.grantWrite;
request.grantFullControl = self.grantFullControl;
request.payload = self.payload;
QCloudCOSXMLService *service = [self tempService];
__weak typeof(request) weakRequest = request;
__weak typeof(self) weakSelf = self;
[request setFinishBlock:^(QCloudCopyObjectResult *_Nonnull result, NSError *_Nonnull error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (self.requstsMetricArrayBlock) {
self.requstsMetricArrayBlock(self.requstMetricArray);
}
self.finishBlock(result, error);
}];
NSMutableString *objectCopySource = [NSMutableString string];
NSString *serviceURL =
[service.configuration.endpoint serverURLWithBucket:self.sourceBucket appID:self.sourceAPPID regionName:self.sourceRegion].absoluteString;
[objectCopySource appendString:[serviceURL componentsSeparatedByString:@"://"][1]];
if (self.sourceObjectVersionID.length) {
[objectCopySource appendFormat:@"/%@/%@", QCloudPercentEscapedStringFromString(self.sourceObject), self.sourceObjectVersionID];
} else {
[objectCopySource appendFormat:@"/%@", QCloudPercentEscapedStringFromString(self.sourceObject)];
}
request.objectCopySource = objectCopySource;
QCloudLogDebugP(@"Copy",@"Object copy source url %@", objectCopySource);
[self.transferManager.cosService PutObjectCopy:request];
}
- (void)multipleCopy {
QCloudInitiateMultipartUploadRequest *initMultipartUploadRequest = [[QCloudInitiateMultipartUploadRequest alloc] init];
initMultipartUploadRequest.bucket = self.bucket;
initMultipartUploadRequest.priority = self.priority;
initMultipartUploadRequest.enableQuic = self.enableQuic;
initMultipartUploadRequest.endpoint = self.endpoint;
initMultipartUploadRequest.networkType = self.networkType;
initMultipartUploadRequest.regionName = self.regionName;
initMultipartUploadRequest.payload = self.payload;
initMultipartUploadRequest.object = self.object;
initMultipartUploadRequest.customHeaders = [self.customHeaders mutableCopy];
__weak typeof(self) weakSelf = self;
__weak typeof(initMultipartUploadRequest) weakRequest = initMultipartUploadRequest;
[initMultipartUploadRequest setFinishBlock:^(QCloudInitiateMultipartUploadResult *result, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (nil == error) {
weakSelf.uploadID = result.uploadId;
[weakSelf uploadCopyParts];
} else {
if (weakSelf.finishBlock) {
weakSelf.finishBlock(nil, error);
}
}
}];
[self.transferManager.cosService InitiateMultipartUpload:initMultipartUploadRequest];
}
- (void)uploadCopyParts {
QCloudCOSXMLService *service = [self tempService];
__weak typeof(self) weakSelf = self;
self.dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
__block int64_t totalComplete = 0;
dispatch_source_set_event_handler(self.dispatchSource, ^{
NSUInteger value = dispatch_source_get_data(weakSelf.dispatchSource);
totalComplete += value;
if (weakSelf.copyProgressBlock) {
weakSelf.copyProgressBlock(totalComplete, weakSelf.sliceCount);
}
if (totalComplete == self.sliceCount) {
[weakSelf finishUploadParts];
dispatch_source_cancel(weakSelf.dispatchSource);
}
});
dispatch_resume(self.dispatchSource);
for (int64_t i = 0; i * kCopySliceLength < self.fileSize; i++) {
@autoreleasepool {
QCloudUploadPartCopyRequest *request = [[QCloudUploadPartCopyRequest alloc] init];
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
request.bucket = self.bucket;
request.customHeaders = [self.customHeaders mutableCopy];
request.payload = self.payload;
request.object = self.object;
request.regionName = self.regionName;
NSMutableString *objectCopySource = [NSMutableString string];
NSString *serviceURL = [service.configuration.endpoint serverURLWithBucket:self.sourceBucket
appID:self.sourceAPPID
regionName:self.sourceRegion]
.absoluteString;
[objectCopySource appendString:[serviceURL componentsSeparatedByString:@"://"][1]];
if (self.sourceObjectVersionID.length) {
[objectCopySource appendFormat:@"/%@/%@", QCloudPercentEscapedStringFromString(self.sourceObject), self.sourceObjectVersionID];
} else {
[objectCopySource appendFormat:@"/%@", QCloudPercentEscapedStringFromString(self.sourceObject)];
}
request.source = objectCopySource;
request.uploadID = self.uploadID;
request.partNumber = i + 1;
request.priority = QCloudAbstractRequestPriorityLow;
int64_t currentOffset = i * kCopySliceLength;
int64_t sliceLength = MIN(self.fileSize - currentOffset, kCopySliceLength);
request.sourceRange = [self copySourceRangeWithFirst:currentOffset last:sliceLength + currentOffset - 1];
__weak typeof(request) weakRequest = request;
__weak typeof(self) weakSelf = self;
[request setFinishBlock:^(QCloudCopyObjectResult *result, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (error) {
[weakSelf onError:error];
[weakSelf cancel];
} else {
QCloudMultipartInfo *info = [[QCloudMultipartInfo alloc] init];
info.eTag = result.eTag;
info.partNumber = [@(i + 1) stringValue];
[weakSelf markPartFinish:info];
dispatch_source_merge_data(weakSelf.dispatchSource, 1);
}
}];
[self.transferManager.cosService UploadPartCopy:request];
}
}
}
- (void)cancel {
}
- (void)finishUploadParts {
QCloudCompleteMultipartUploadRequest *request = [[QCloudCompleteMultipartUploadRequest alloc] init];
request.bucket = self.bucket;
request.object = self.object;
request.regionName = self.regionName;
request.payload = self.payload;
request.uploadId = self.uploadID;
request.priority = self.priority;
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
QCloudCompleteMultipartUploadInfo *info = [[QCloudCompleteMultipartUploadInfo alloc] init];
[self.uploadParts sortUsingComparator:^NSComparisonResult(QCloudMultipartInfo *obj1, QCloudMultipartInfo *obj2) {
if (obj1.partNumber.longLongValue > obj2.partNumber.longLongValue) {
return NSOrderedDescending;
} else {
return NSOrderedAscending;
}
}];
info.parts = self.uploadParts;
request.parts = info;
__weak typeof(request) weakRequest = request;
__weak typeof(self) weakSelf = self;
[request setFinishBlock:^(QCloudUploadObjectResult *result, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (self.requstsMetricArrayBlock) {
self.requstsMetricArrayBlock(self.requstMetricArray);
}
if (nil == error) {
QCloudCopyObjectResult *copyResult = [[QCloudCopyObjectResult alloc] init];
copyResult.eTag = result.eTag;
copyResult.lastModified = self.lastModified;
if (weakSelf.finishBlock) {
weakSelf.finishBlock(copyResult, error);
}
} else {
if (weakSelf.finishBlock) {
weakSelf.finishBlock(nil, error);
}
}
}];
[self.transferManager.cosService CompleteMultipartUpload:request];
}
- (QCloudCOSXMLService *)tempService {
static dispatch_once_t onceToken;
static QCloudCOSXMLService *service;
dispatch_once(&onceToken, ^{
QCloudServiceConfiguration *configuration = [QCloudServiceConfiguration new];
configuration.signatureProvider = self.transferManager.configuration.signatureProvider;
configuration.appID = self.sourceAPPID;
configuration.endpoint.useHTTPS = self.transferManager.configuration.endpoint.useHTTPS;
QCloudCOSXMLEndPoint *endpoint = [[QCloudCOSXMLEndPoint alloc] init];
endpoint.regionName = self.sourceRegion;
endpoint.serviceName = self.transferManager.configuration.endpoint.serviceName;
endpoint.useHTTPS = self.transferManager.configuration.endpoint.useHTTPS;
configuration.endpoint = endpoint;
service = [QCloudCOSXMLService registerCOSXMLWithConfiguration:configuration withKey:kTempServiceKey];
});
return service;
}
- (void)setFinishBlock:(void (^)(QCloudCopyObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (NSString *)copySourceRangeWithFirst:(int64_t)first last:(int64_t)last {
NSString *result = [NSString stringWithFormat:@"bytes=%lld-%lld", first, last];
return result;
}
- (void)markPartFinish:(QCloudMultipartInfo *)info {
if (!info) {
return;
}
[self.uploadParts addObject:info];
}
- (NSMutableArray *)uploadParts {
if (!_uploadParts) {
_uploadParts = [NSMutableArray array];
}
return _uploadParts;
}
- (void)setCopyProgressBlock:(void (^)(int64_t, int64_t))copyProgressBlock {
_copyProgressBlock = copyProgressBlock;
}
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey {
NSData *data = [customerKey dataUsingEncoding:NSUTF8StringEncoding];
NSString *excryptAES256Key = [data base64EncodedStringWithOptions:0]; // base64
NSString *base64md5key = QCloudEncrytNSDataMD5Base64(data);
self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-algorithm"] = @"AES256";
self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-key"] = excryptAES256Key;
self.customHeaders[@"x-cos-copy-source-server-side-encryption-customer-key-MD5"] = base64md5key;
}
@end

View File

@@ -0,0 +1,144 @@
//
// QCloudCOSXMLDownloadObjectRequest.h
// Pods-QCloudCOSXMLDemo
//
// Created by karisli(李雪) on 2018/8/23.
//
#import <QCloudCore/QCloudCore.h>
@class QCloudCOSTransferMangerService;
/**
### 示例
@code
QCloudCOSXMLDownloadObjectRequest * request = [QCloudCOSXMLDownloadObjectRequest new];
request.bucket = @"bucket";
request.object = @"object";
request.enableQuic = YES;
request.localCacheDownloadOffset = 本地已下载的文件大小
[request setFinishBlock:^(id _Nullable outputObject, NSError * _Nullable error) {
}];
[[QCloudCOSTransferMangerService costransfermangerServiceForKey:ServiceKey]
DownloadObject:request];
*/
@interface QCloudCOSXMLDownloadObjectRequest : QCloudAbstractRequest
/**
设置响应头部中的 Content-Type参数
*/
@property (strong, nonatomic) NSString *responseContentType;
/**
设置响应头部中的Content-Language参数
*/
@property (strong, nonatomic) NSString *responseContentLanguage;
/**
设置响应头部中的Content-Expires参数
*/
@property (strong, nonatomic) NSString *responseContentExpires;
/**
设置响应头部中的Cache-Control参数
*/
@property (strong, nonatomic) NSString *responseCacheControl;
/**
设置响应头部中的 Content-Disposition 参数。
*/
@property (strong, nonatomic) NSString *responseContentDisposition;
/**
设置响应头部中的 Content-Encoding 参数。
*/
@property (strong, nonatomic) NSString *responseContentEncoding;
/**
RFC 2616 中定义的指定文件下载范围以字节bytes为单位
*/
@property (strong, nonatomic) NSString *range;
/**
如果文件修改时间晚于指定时间,才返回文件内容。否则返回 412 (not modified)
*/
@property (strong, nonatomic) NSString *ifModifiedSince;
/**
如果文件修改时间早于或等于指定时间,才返回文件内容。否则返回 412 (precondition failed)
*/
@property (strong, nonatomic) NSString *ifUnmodifiedModifiedSince;
/**
当 ETag 与指定的内容一致,才返回文件。否则返回 412 (precondition failed)
*/
@property (strong, nonatomic) NSString *ifMatch;
/**
当 ETag 与指定的内容不一致,才返回文件。否则返回 304 (not modified)
*/
@property (strong, nonatomic) NSString *ifNoneMatch;
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
桶所在地域
*/
@property (strong, nonatomic) NSString *regionName;
/**
该选项设置为YES后在下载完成后会比对COS上储存的文件MD5和下载到本地的文件MD5如果MD5有差异的话会返回-340013错误码。
目前默认关闭。
*/
@property (assign, nonatomic) BOOL enableMD5Verification;
/**
指定 Object 的 VersionID (在开启多版本的情况下)
*/
@property (strong, nonatomic) NSString *versionID;
/**
如果存在改参数,则数据会下载到改路径指名的地址下面,而不会写入内存中。
*/
@property (nonatomic, strong) NSURL *downloadingURL;
/**
本地已经下载的数据偏移量如果使用则会从改位置开始下载如果不使用则从头开始下载如果您使用了Range参数则需要注意改参数。
*/
@property (nonatomic, assign) int64_t localCacheDownloadOffset;
@property (nonatomic, weak) QCloudCOSTransferMangerService *transferManager;
/*
在进行HTTP请求的时候可以通过设置该参数来设置自定义的一些头部信息。
通常情况下携带特定的额外HTTP头部可以使用某项功能如果是这类需求可以通过设置该属性来实现。
*/
@property (strong, nonatomic) NSMutableDictionary *customHeaders;
/**
指定是否使用分块及续传下载,默认为 FALSE。
*/
@property (assign, nonatomic)BOOL resumableDownload;
/**
使用分块及续传下载时,指定任务记录文件的路径
*/
@property (strong, nonatomic) NSString *resumableTaskFile;
/**
续传时,是否将续传前的进度并入进度回调中。默认 NO
例如,下载一个 100m文件已经下载20m续传是
设置NO则进度将会从0走到80。
设置YES则进度将会从20走到100。
*/
@property (assign, nonatomic) BOOL resumeLocalProcess;
/// 是否使用路径检查true为开启false为关闭默认为true
@property (assign, nonatomic) BOOL objectKeySimplifyCheck;
/// 是否开启crc64校验默认开启。
@property (assign, nonatomic) BOOL enablePartCrc64;
//针对本次下载行流量控制的限速值,必须为数字,单位默认为 bit/s。限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s如果超出该范围将返回400错误
@property (nonatomic, assign) NSInteger trafficLimit;
- (void)setCOSServerSideEncyption;
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey;
@end

View File

@@ -0,0 +1,470 @@
//
// QCloudCOSXMLDownloadObjectRequest.m
// Pods-QCloudCOSXMLDemo
//
// Created by karisli() on 2018/8/23.
//
#import "QCloudCOSXMLDownloadObjectRequest.h"
#import "QCloudGetObjectRequest.h"
#import "QCloudGetObjectRequest+Custom.h"
#import "QCloudCOSTransferMangerService.h"
#import "QCloudCOSXMLService+Transfer.h"
#import "QCloudHeadObjectRequest.h"
#import <QCloudCore/NSMutableData+QCloud_CRC.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#define CRC64PartLength 10 * 1024 * 1024
@interface QCloudCOSXMLDownloadObjectRequest()
@property (nonatomic,assign)NSInteger retryCount;
//
@property (nonatomic, strong) NSPointerArray *requestCacheArray;
@property (nonatomic, strong) dispatch_source_t queueSource;
@property (nonatomic, strong) NSURL *_Nonnull downloadingTempURL;
@property (nonatomic,strong)NSMutableDictionary * partCrc64Map;
@property (nonatomic,strong)dispatch_queue_t crcQueue;
@property (nonatomic,assign)NSInteger crc64Start;
@property (nonatomic,assign)NSInteger crc64Complete;
@property (nonatomic,strong)NSString * partCrc64Filepath;
@end
@implementation QCloudCOSXMLDownloadObjectRequest
#pragma clang diagnostic pop
- (void)dealloc {
QCloudLogInfoP(@"Download",@"QCloudCOSXMLDownloadObjectRequest = %@ dealloc", self);
if (NULL != _queueSource) {
dispatch_source_cancel(_queueSource);
}
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.enablePartCrc64 = YES;
self.objectKeySimplifyCheck = YES;
_customHeaders = [NSMutableDictionary dictionary];
_partCrc64Map = [NSMutableDictionary new];
_requestCacheArray = [NSPointerArray weakObjectsPointerArray];
_crcQueue = dispatch_queue_create("com.qcloud.crc64.queue", DISPATCH_QUEUE_SERIAL);
return self;
}
- (void)fakeStart {
if(!self.resumableDownload){
[self startGetObject];
return;
}else{
if(!self.resumableTaskFile){
if(!self.downloadingURL){
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:@"InvalidArgument:您输入的downloadingURL不合法请检查后使用"];
if(self.finishBlock){
self.finishBlock(nil, error);
return;
}
}
self.resumableTaskFile = [NSString stringWithFormat:@"%@.cosresumabletask",self.downloadingURL.relativePath];
}
QCloudHeadObjectRequest *headReq = [QCloudHeadObjectRequest new];
headReq.bucket = self.bucket;
headReq.payload = self.payload;
headReq.regionName = self.regionName;
headReq.object = self.object;
headReq.enableQuic = self.enableQuic;
headReq.endpoint = self.endpoint;
headReq.networkType = self.networkType;
[headReq setFinishBlock:^(id _Nullable outputObject, NSError * _Nullable error) {
if(error){
self.finishBlock(outputObject, error);
return;
}
BOOL exist = [[NSFileManager defaultManager] fileExistsAtPath:self.resumableTaskFile];
NSMutableDictionary *lowercaseStringDic = [NSMutableDictionary dictionary];
[(NSDictionary*)outputObject enumerateKeysAndObjectsUsingBlock:^(NSString *key, id _Nonnull obj, BOOL * _Nonnull stop) {
[lowercaseStringDic setValue:obj forKey:key.lowercaseString];
}];
if (!exist) {
[[NSFileManager defaultManager] createFileAtPath:self.resumableTaskFile contents:[NSData data] attributes:nil];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:lowercaseStringDic[@"last-modified"] forKey:@"lastModified"];
[dic setValue:lowercaseStringDic[@"content-length"] forKey:@"contentLength"];
[dic setValue:lowercaseStringDic[@"etag"] forKey:@"etag"];
[dic setValue:lowercaseStringDic[@"x-cos-hash-crc64ecma"] forKey:@"crc64ecma"];
NSError *parseError;
if(dic){
NSData *info =[NSJSONSerialization dataWithJSONObject:[dic copy] options:NSJSONWritingPrettyPrinted error:&parseError];
NSError *writeDataError;
[info writeToFile:self.resumableTaskFile options:0 error:&writeDataError];
}
}else{
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:self.resumableTaskFile];
if(jsonData){
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
//
if(![dic[@"contentLength"] isEqualToString:lowercaseStringDic[@"content-length"]] ||
![dic[@"lastModified"] isEqualToString:lowercaseStringDic[@"last-modified"]] ||
![dic[@"etag"] isEqualToString:lowercaseStringDic[@"etag"]] ||
![dic[@"crc64ecma"] isEqualToString:lowercaseStringDic[@"x-cos-hash-crc64ecma"]]){
QCloudRemoveFileByPath(self.resumableTaskFile);
if (self.enablePartCrc64) {
self.partCrc64Map = [NSMutableDictionary new];
self.crc64Start = 0;
self.crc64Complete = 0;
}
[[NSFileManager defaultManager] createFileAtPath:self.resumableTaskFile contents:[NSData data] attributes:nil];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:lowercaseStringDic[@"last-modified"] forKey:@"lastModified"];
[dic setValue:lowercaseStringDic[@"content-length"] forKey:@"contentLength"];
[dic setValue:lowercaseStringDic[@"etag"] forKey:@"etag"];
[dic setValue:lowercaseStringDic[@"x-cos-hash-crc64ecma"] forKey:@"crc64ecma"];
NSError *parseError;
NSData *info =[NSJSONSerialization dataWithJSONObject:[dic copy] options:NSJSONWritingPrettyPrinted error:&parseError];
NSError *writeDataError;
[info writeToFile:self.resumableTaskFile options:0 error:&writeDataError];
} else{
NSArray *tasks = dic[@"downloadedBlocks"];
self.localCacheDownloadOffset = [(NSString *)tasks.lastObject[@"to"] integerValue];
}
}
}
[self startGetObject];
}];
[self.transferManager.cosService HeadObject:headReq];
}
}
-(void)calculateCrc64:(NSURL *)filePath fileSize:(long long)fileSize{
if (!filePath) {
return;
}
if (!QCloudFileExist(filePath.path)) {
return;
}
NSFileHandle *handler = [NSFileHandle fileHandleForReadingAtPath:filePath.path];
[handler seekToFileOffset:self.crc64Complete];
if (fileSize == 0) {
fileSize = QCloudFileSize(filePath.path);
}
NSInteger readLength = fileSize - self.crc64Complete > CRC64PartLength ?CRC64PartLength:fileSize - self.crc64Complete;
if (readLength == 0) {
return;
}
NSData *data = [handler readDataOfLength:readLength];
NSString * range = [NSString stringWithFormat:@"%ld-%ld",self.crc64Complete,self.crc64Complete + readLength];
uint64_t crc64 = [[data mutableCopy] qcloud_crc64];
[self.partCrc64Map setObject:@(crc64) forKey:range];
QCloudLogDebugN(@"CRC64", @"calculateCrc64,partRang:%@,crc64:%ld",range,crc64);
NSData *info =[NSJSONSerialization dataWithJSONObject:[self.partCrc64Map copy] options:NSJSONWritingPrettyPrinted error:nil];
[info writeToFile:self.partCrc64Filepath options:0 error:nil];
}
-(uint64_t)mergePartCrc64{
NSArray<NSString *> *sortedKeys = [self.partCrc64Map.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSString *key1, NSString *key2) {
NSInteger start1 = [[[key1 componentsSeparatedByString:@"-"] firstObject] integerValue];
NSInteger start2 = [[[key2 componentsSeparatedByString:@"-"] firstObject] integerValue];
return [@(start1) compare:@(start2)];
}];
__block uint64_t mergedCRC = 0;
[sortedKeys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
NSArray<NSString *> *components = [key componentsSeparatedByString:@"-"];
if (components.count != 2) return;
NSInteger start = [components[0] integerValue];
NSInteger end = [components[1] integerValue];
NSNumber *crcValue = self.partCrc64Map[key];
uint64_t chunkLength = (uint64_t)(end - start);
mergedCRC = [[NSMutableData new] qcloud_crc64ForCombineCRC1:mergedCRC CRC2:[crcValue unsignedLongLongValue] length:chunkLength];
}];
return mergedCRC;
}
- (uint64_t)crc64ForFileAtPath:(NSString *)filePath
chunkSize:(size_t)chunkSize
length:(size_t)length{
// 1.
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
if (!fileHandle) {
return 0;
}
// 2.
unsigned long long fileSize = QCloudFileSize(filePath);
if (length > 0) {
fileSize = length;
}
// 3. CRC
uint64_t combinedCRC = 0;
unsigned long long offset = 0;
@try {
while (offset < fileSize) {
@autoreleasepool {
// 4.
NSUInteger remaining = (NSUInteger)(fileSize - offset);
NSUInteger readLength = MIN(remaining, chunkSize);
[fileHandle seekToFileOffset:offset];
NSData *chunk = [fileHandle readDataOfLength:readLength];
if (chunk.length == 0) break;
// 5. CRC
NSMutableData *mutableChunk = [chunk mutableCopy];
uint64_t chunkCRC = [mutableChunk qcloud_crc64];
// 6. CRC
if (offset == 0) {
combinedCRC = chunkCRC;
} else {
combinedCRC = [mutableChunk qcloud_crc64ForCombineCRC1:combinedCRC
CRC2:chunkCRC
length:chunk.length];
}
offset += chunk.length;
}
}
} @catch (NSException *exception) {
return 0;
} @finally {
[fileHandle closeFile];
}
return combinedCRC;
}
-(void)loadLocalCrc64{
self.crc64Start = self.localCacheDownloadOffset;
self.crc64Complete = self.crc64Start;
}
- (void)startGetObject {
if (self.enablePartCrc64) {
self.partCrc64Filepath = [NSString stringWithFormat:@"%@.partcrc64",self.downloadingURL.relativePath];
}
QCloudLogInfoP(@"Download",@"begin download object:%@,localCacheDownloadOffset=%ld", self.object, self.localCacheDownloadOffset);
QCloudGetObjectRequest *request = [QCloudGetObjectRequest new];
request.objectKeySimplifyCheck = self.objectKeySimplifyCheck;
request.trafficLimit = self.trafficLimit;
request.payload = self.payload;
request.customHeaders = [self.customHeaders mutableCopy];
request.downloadingURL = self.downloadingURL;
self.downloadingTempURL = request.downloadingTempURL;
if (self.enablePartCrc64 && self.localCacheDownloadOffset > 0) {
if (QCloudFileExist(self.partCrc64Filepath)) {
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:self.partCrc64Filepath];
if(jsonData){
self.partCrc64Map = [[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil] mutableCopy];
uint64_t saveCrc64 = [self mergePartCrc64];
NSArray<NSString *> *sortedKeys = [self.partCrc64Map.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSString *key1, NSString *key2) {
NSInteger start1 = [[[key1 componentsSeparatedByString:@"-"] firstObject] integerValue];
NSInteger start2 = [[[key2 componentsSeparatedByString:@"-"] firstObject] integerValue];
return [@(start1) compare:@(start2)];
}];
uint64_t length = [sortedKeys.lastObject componentsSeparatedByString:@"-"].lastObject.integerValue;
uint64_t localCrc64 = [self crc64ForFileAtPath:self.downloadingTempURL.path chunkSize:CRC64PartLength length:length];
if (localCrc64 != saveCrc64) {
QCloudRemoveFileByPath(self.resumableTaskFile);
QCloudRemoveFileByPath(self.partCrc64Filepath);
self.crc64Start = 0;
self.crc64Complete = 0;
self.partCrc64Map = [NSMutableDictionary new];
self.localCacheDownloadOffset = 0;
QCloudRemoveFileByPath(self.downloadingTempURL.relativePath);
}else{
[self loadLocalCrc64];
}
}else{
[self loadLocalCrc64];
}
}else{
[self loadLocalCrc64];
}
}
request.localCacheDownloadOffset = self.localCacheDownloadOffset;
request.regionName = self.regionName;
request.enableMD5Verification = self.enableMD5Verification;
request.versionID = self.versionID;
__block int64_t currentTotalBytesDownload = 0;
__weak typeof(self) weakSelf = self;
[request setDownProcessBlock:^(int64_t bytesDownload, int64_t totalBytesDownload, int64_t totalBytesExpectedToDownload) {
__strong typeof(weakSelf) strongSelf = self;
if (!strongSelf) return;
currentTotalBytesDownload = totalBytesDownload;
int64_t _localCacheDownloadOffset = 0;
if (strongSelf.resumeLocalProcess) {
_localCacheDownloadOffset = strongSelf.localCacheDownloadOffset;
}
if(strongSelf.downProcessBlock){
strongSelf.downProcessBlock(bytesDownload, totalBytesDownload + _localCacheDownloadOffset, totalBytesExpectedToDownload + _localCacheDownloadOffset);
}
if (self.enablePartCrc64) {
const int64_t effectiveTotalDownload = totalBytesDownload + strongSelf.localCacheDownloadOffset;
if (effectiveTotalDownload - strongSelf.crc64Start >= CRC64PartLength) {
strongSelf.crc64Start += CRC64PartLength;
dispatch_async(strongSelf.crcQueue, ^{
[strongSelf calculateCrc64:strongSelf.downloadingTempURL fileSize:0];
@synchronized(strongSelf) {
strongSelf.crc64Complete = strongSelf.crc64Start;
}
});
}
}
}];
[request setFinishBlock:^(id _Nullable outputObject, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = self;
if(strongSelf.resumableDownload){
//便
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:self.resumableTaskFile];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
if(jsonData){
dic = [[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil] mutableCopy];
if (dic == nil) {
dic = [NSMutableDictionary dictionary];
}
}
if(error){
if (self.enablePartCrc64) {
[self calculateCrc64:self.downloadingTempURL fileSize:currentTotalBytesDownload + strongSelf.localCacheDownloadOffset];
}
NSMutableArray *tasks = [dic[@"downloadedBlocks"] mutableCopy];
if(!tasks){
tasks = [NSMutableArray array];
}
NSString *fromStr = [NSString stringWithFormat:@"%lld",strongSelf.localCacheDownloadOffset];
NSString *toStr = [NSString stringWithFormat:@"%lld",currentTotalBytesDownload + strongSelf.localCacheDownloadOffset];
[tasks addObject:@{@"from":fromStr,@"to":toStr}];
[dic setValue: [tasks copy] forKey:@"downloadedBlocks"];
NSError *parseError;
NSData *info =[NSJSONSerialization dataWithJSONObject:[dic copy] options:NSJSONWritingPrettyPrinted error:&parseError];
NSError *writeDataError;
if(info && !parseError){
[info writeToFile:strongSelf.resumableTaskFile options:0 error:&writeDataError];
}
if(writeDataError){
error = writeDataError;
}
if(self.finishBlock && error.code != QCloudNetworkErrorCodeCanceled){
strongSelf.finishBlock(outputObject, error);
}
}else{
//crc64
if(!dic[@"crc64ecma"]){
QCloudRemoveFileByPath(strongSelf.resumableTaskFile);
QCloudRemoveFileByPath(strongSelf.partCrc64Filepath);
if(self.finishBlock){
strongSelf.finishBlock(outputObject, error);
}
return;
}
QCloudRemoveFileByPath(strongSelf.resumableTaskFile);
uint64_t localCrc64;
if (self.enablePartCrc64 == YES) {
[self calculateCrc64:self.downloadingURL fileSize:0];
localCrc64 = [self mergePartCrc64];
NSString *localCrc64Str = [NSString stringWithFormat:@"%llu",localCrc64];
QCloudRemoveFileByPath(strongSelf.partCrc64Filepath);
if(![localCrc64Str isEqualToString:dic[@"crc64ecma"]]){
//crc64
self.crc64Start = 0;
self.crc64Complete = 0;
self.partCrc64Map = [NSMutableDictionary new];
self.localCacheDownloadOffset = 0;
if (self.retryCount >= 3) {
NSString * message = [NSString stringWithFormat:@"本地文件与远端文件不一致请重新下载远端CRC64 值:%@, 本地文件 CRC64值:%@",
dic[@"crc64ecma"], localCrc64Str];
strongSelf.finishBlock(nil, [NSError errorWithDomain:kQCloudNetworkDomain code:QCloudNetworkErrorCodeNotMatch userInfo:@{NSLocalizedDescriptionKey:message}]);
return;
}else{
QCloudRemoveFileByPath(strongSelf.downloadingURL.relativePath);
self.retryCount ++;
[self fakeStart];
}
return;
}
}
if(self.finishBlock){
strongSelf.finishBlock(outputObject, error);
}
}
}else{
if(self.finishBlock){
strongSelf.finishBlock(outputObject, error);
}
}
}];
request.responseContentType = self.responseContentType;
request.responseContentLanguage = self.responseContentLanguage;
request.responseContentExpires = self.responseContentExpires;
request.responseCacheControl = self.responseCacheControl;
request.responseContentDisposition = self.responseContentDisposition;
request.responseContentEncoding = self.responseContentEncoding;
request.range = self.range;
request.ifModifiedSince = self.ifModifiedSince;
request.ifUnmodifiedModifiedSince = self.ifUnmodifiedModifiedSince;
request.ifMatch = self.ifMatch;
request.ifNoneMatch = self.ifNoneMatch;
request.object = self.object;
request.bucket = self.bucket;
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
[self.transferManager.cosService GetObject:request];
[self.requestCacheArray addPointer:(__bridge void *_Nullable)(request)];
}
-(void)cancel{
[self.requestCacheArray addPointer:(__bridge void *_Nullable)([NSObject new])];
[self.requestCacheArray compact];
if (NULL != _queueSource) {
dispatch_source_cancel(_queueSource);
}
NSMutableArray *cancelledRequestIDs = [NSMutableArray array];
NSPointerArray *tmpRequestCacheArray = [self.requestCacheArray copy];
for (QCloudHTTPRequest *request in tmpRequestCacheArray) {
if (request != nil) {
[cancelledRequestIDs addObject:[NSNumber numberWithLongLong:request.requestID]];
[request cancel];
}
}
[[QCloudHTTPSessionManager shareClient] cancelRequestsWithID:cancelledRequestIDs];
[super cancel];
}
- (void)setCOSServerSideEncyption {
self.customHeaders[@"x-cos-server-side-encryption"] = @"AES256";
}
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey {
NSData *data = [customerKey dataUsingEncoding:NSUTF8StringEncoding];
NSString *excryptAES256Key = [data base64EncodedStringWithOptions:0]; // base64
NSString *base64md5key = QCloudEncrytNSDataMD5Base64(data);
self.customHeaders[@"x-cos-server-side-encryption-customer-algorithm"] = @"AES256";
self.customHeaders[@"x-cos-server-side-encryption-customer-key"] = excryptAES256Key;
self.customHeaders[@"x-cos-server-side-encryption-customer-key-MD5"] = base64md5key;
}
@end

View File

@@ -0,0 +1,172 @@
//
// QCloudCOSXMLUploadObjectRequest.h
// Pods
//
// Created by Dong Zhao on 2017/5/23.
//
//
#import <QCloudCore/QCloudCore.h>
#import "QCloudCOSStorageClassEnum.h"
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXTERN NSString *_Nullable const QCloudUploadResumeDataKey;
typedef NSData *QCloudCOSXMLUploadObjectResumeData;
@class QCloudUploadObjectResult;
@class QCloudInitiateMultipartUploadResult;
@class QCloudCOSXMLUploadObjectRequest;
typedef void (^InitMultipleUploadFinishBlock)(QCloudInitiateMultipartUploadResult *_Nullable multipleUploadInitResult,
QCloudCOSXMLUploadObjectResumeData _Nullable resumeData);
typedef void (^RequestsMetricArrayBlock)(NSMutableArray *_Nullable requstMetricArray);
/**
COSXML上传对象接口。在上传小于1MB的文件时通过该request来上传的话会生成一个简单上传putObjectRequset
将整个对象直接上传。
如果上传的对象大小大于1MB时我们会在内部进行分片上传的处理将文件切分成数个1MB大小的块
然后通过并行分快上传的方式进行上传。
### 示例
@code
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];
NSURL* url = @"文件的URL";
put.object = @"文件名.jpg";
put.bucket = @"bucket名";
put.body = url;
[put setSendProcessBlock:^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
NSLog(@"upload %lld totalSend %lld aim %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
}];
[put setFinishBlock:^(id outputObject, NSError *error) {
}];
[[QCloudCOSTransferMangerService defaultCOSTRANSFERMANGER] UploadObject:put];
*/
@interface QCloudCOSXMLUploadObjectRequest<BodyType> : QCloudAbstractRequest
//自定义分片大小
@property (nonatomic, assign) NSUInteger sliceSize;
//自定义分片阈值
@property (nonatomic, assign) NSInteger mutilThreshold;
@property (nonatomic, assign) QCloudAbstractRequestPriority uploadPriority;
/**
上传文件对象的文件名也是对象的key请注意文件名中不可以含有问号即"?"字符
*/
@property (strong, nonatomic) NSString *object;
@property (strong, nonatomic) QCloudHTTPRetryHanlder *_Nullable retryHandler;
/**
存储桶名称
*/
@property (strong, nonatomic) NSString *bucket;
/**
需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量
*/
@property (strong, nonatomic) BodyType body;
/**
RFC 2616 中定义用于指示资源的MIME类型将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *contentType;
/**
RFC 2616 中定义的缓存策略,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *cacheControl;
/**
RFC 2616 中定义的文件名称,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *contentDisposition;
/**
当使用 Expect: 100-continue 时,在收到服务端确认后,才会发送请求内容
*/
@property (strong, nonatomic) NSString *expect;
/**
RFC 2616 中定义的过期时间,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *expires;
@property (strong, nonatomic) NSString *contentSHA1;
//针对本次上传进行流量控制的限速值,必须为数字,单位默认为 bit/s。限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s如果超出该范围将返回400错误
@property (nonatomic, assign) NSInteger trafficLimit;
/**
对象的存储级别
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL(Access Control List) 属性。有效值privatepublic-read-writepublic-read,默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者读写权限。格式: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
*/
@property (strong, nonatomic) NSString *grantFullControl;
/**
表明该请求是否已经被中断
*/
@property (assign, atomic, readonly) BOOL aborted;
/**
如果该request产生了分片上传的请求那么在分片上传初始化完成后会通过这个block来回调
可以在该回调block中获取分片完成后的bucket, key, uploadID,以及用于后续上传失败后恢复上传的ResumeData。
*/
@property (nonatomic, copy) InitMultipleUploadFinishBlock initMultipleUploadFinishBlock;
@property (nonatomic, copy) RequestsMetricArrayBlock requstsMetricArrayBlock;
/**
是否在上传完成以后,将 COS 返回的文件MD5与本地文件算出来的md5进行校验。默认开启如果校验出错
文件仍然会被上传到 COS, 不过我们会在本地抛出校验失败的error。
*/
@property (nonatomic, assign) BOOL enableMD5Verification __attribute__((deprecated("该属性已过期请用enableVerification替换")));
/**
是否在上传完成以后,将 COS 返回的文件MD5与本地文件算出来的md5进行校验。默认开启如果校验出错
文件仍然会被上传到 COS, 不过我们会在本地抛出校验失败的error。
*/
@property (nonatomic, assign) BOOL enableVerification;
/**
在进行HTTP请求的时候可以通过设置该参数来设置自定义的一些头部信息。
通常情况下携带特定的额外HTTP头部可以使用某项功能如果是这类需求可以通过设置该属性来实现。
*/
@property (strong, nonatomic) NSMutableDictionary *_Nullable customHeaders;
@property (strong, nonatomic) NSString *_Nullable regionName;
@property (assign, nonatomic) bool uploadBodyIsCompleted;
/**
上传完成后会通过该block回调。若error为空可视为成功。
@param QCloudRequestFinishBlock 上传完成后的回调
*/
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
#pragma resume
/**
在初始化分片上传完成以后会回调的block中获取 resumeData,通过 resumeData 生成一个分片上传的请求;
*/
+ (instancetype)requestWithRequestData:(QCloudCOSXMLUploadObjectResumeData _Nullable)resumeData;
/**
主动调用取消,并且产生 resumetData
*/
- (QCloudCOSXMLUploadObjectResumeData)cancelByProductingResumeData:(NSError *__autoreleasing *)error;
- (void)abort:(QCloudRequestFinishBlock _Nullable)finishBlock;
- (void)setCOSServerSideEncyption;
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *_Nonnull)customerKey;
- (void)setCOSServerSideEncyptionWithKMSCustomKey:(NSString *_Nonnull)customerKey jsonStr:(NSString *_Nonnull)jsonStr;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,898 @@
//
// QCloudCOSXMLUploadObjectRequest.m
// Pods
//
// Created by Dong Zhao on 2017/5/23.
//
//
#import "QCloudCOSXMLUploadObjectRequest.h"
#import "QCloudPutObjectRequest.h"
#import "QCloudCOSXMLService+Transfer.h"
#import "QCloudInitiateMultipartUploadRequest.h"
#import "QCloudUploadPartRequest.h"
#import "QCloudCompleteMultipartUploadRequest.h"
#import "QCloudMultipartInfo.h"
#import "QCloudCompleteMultipartUploadInfo.h"
#import "QCloudCOSXMLUploadObjectRequest_Private.h"
#import "QCloudListMultipartRequest.h"
#import "QCloudCOSXMLServiceUtilities.h"
#import "QCloudCOSTransferMangerService.h"
#import "QCloudAbortMultipfartUploadRequest.h"
#import <QCloudCore/QCloudUniversalPath.h>
#import <QCloudCore/QCloudSandboxPath.h>
#import <QCloudCore/QCloudMediaPath.h>
#import <QCloudCore/QCloudBundlePath.h>
#import <QCloudCore/QCloudNetworkingAPI.h>
#import <QCloudCore/QCloudUniversalPathFactory.h>
#import "QCloudCOSTransferMangerService.h"
#import "QCloudPutObjectRequest+Custom.h"
#import <QCloudCore/QCloudSupervisoryRecord.h>
#import <QCloudCore/QCloudHTTPRetryHanlder.h>
#import <QCloudCore/QualityDataUploader.h>
static NSUInteger kQCloudCOSXMLUploadLengthLimit = 1 * 1024 * 1024;
static NSUInteger kQCloudCOSXMLUploadSliceLength = 1 * 1024 * 1024;
static NSUInteger kQCloudCOSXMLMD5Length = 32;
static NSUInteger kQCloudCOSXMLSha1Length = 40;
@interface QCloudCOSXMlResumeUploadInfo : NSObject
@property (nonatomic, strong) NSString *localPath;
@property (strong, nonatomic) NSString *object;
@property (strong, nonatomic) NSString *bucket;
@end
@implementation QCloudCOSXMlResumeUploadInfo
@end
NSString *const QCloudUploadResumeDataKey = @"__QCloudUploadResumeDataKey__";
@interface QCloudCOSXMLUploadObjectRequest () <QCloudHttpRetryHandlerProtocol> {
NSRecursiveLock *_recursiveLock;
NSRecursiveLock *_progressLock;
NSUInteger uploadedSize;
//0
NSUInteger startPartNumber;
BOOL isChange;
}
@property (nonatomic, assign) int64_t totalBytesSent;
@property (nonatomic, assign) NSUInteger dataContentLength;
@property (nonatomic, strong) dispatch_source_t queueSource;
//
@property (nonatomic, strong) NSMutableArray<QCloudMultipartInfo *> *uploadParts;
@property (nonatomic, strong) NSString *uploadId;
@property (nonatomic, strong) NSPointerArray *requestCacheArray;
@property (strong, nonatomic) NSMutableArray *requstMetricArray;
@end
@implementation QCloudCOSXMLUploadObjectRequest
- (void)dealloc {
QCloudLogInfoP(@"Upload",@"QCloudCOSXMLUploadObjectRequest = %@ dealloc", self);
if (NULL != _queueSource) {
dispatch_source_cancel(_queueSource);
}
}
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{
@"uploadParts" : [QCloudMultipartInfo class],
};
}
- (instancetype)init {
self = [super init];
if (!self) {
return self;
}
_uploadBodyIsCompleted = YES;
_requestCacheArray = [NSPointerArray weakObjectsPointerArray];
_customHeaders = [NSMutableDictionary dictionary];
_aborted = NO;
_recursiveLock = [NSRecursiveLock new];
_progressLock = [NSRecursiveLock new];
_requstMetricArray = [NSMutableArray array];
_mutilThreshold = kQCloudCOSXMLUploadLengthLimit;
_enableMD5Verification = YES;
_enableVerification = YES;
_retryHandler = [QCloudHTTPRetryHanlder defaultRetryHandler];
startPartNumber = -1;
self.priority = QCloudAbstractRequestPriorityHigh;
return self;
}
- (void)setEnableVerification:(BOOL)enableVerification{
_enableVerification = enableVerification;
_enableMD5Verification = enableVerification;
}
- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dictionary {
NSMutableDictionary *dict = [dictionary mutableCopy];
if ([dictionary valueForKey:@"body"]) {
NSDictionary *universalPathDict = [dictionary valueForKey:@"body"];
QCloudUniversalPathType type = [[universalPathDict valueForKey:@"type"] integerValue];
NSString *originURL = [universalPathDict valueForKey:@"originURL"];
QCloudUniversalPath *path;
switch (type) {
case QCLOUD_UNIVERSAL_PATH_TYPE_FIXED:
path = [[QCloudUniversalFixedPath alloc] initWithStrippedURL:originURL];
break;
case QCLOUD_UNIVERSAL_PATH_TYPE_ADJUSTABLE:
path = [[QCloudUniversalAdjustablePath alloc] initWithStrippedURL:originURL];
break;
case QCLOUD_UNIVERSAL_PATH_TYPE_SANDBOX:
path = [[QCloudSandboxPath alloc] initWithStrippedURL:originURL];
break;
case QCLOUD_UNIVERSAL_PATH_TYPE_BUNDLE:
path = [[QCloudBundlePath alloc] initWithStrippedURL:originURL];
break;
case QCLOUD_UNIVERSAL_PATH_TYPE_MEDIA:
path = [[QCloudMediaPath alloc] initWithStrippedURL:originURL];
break;
default:
break;
}
[dict setValue:path forKey:@"body"];
}
return [dict copy];
}
- (void)continueMultiUpload:(QCloudListPartsResult *)existParts {
_uploadParts = [NSMutableArray new];
NSArray *allParts = [self getFileLocalUploadParts];
NSMutableDictionary *existMap = [NSMutableDictionary new];
for (QCloudMultipartUploadPart *part in existParts.parts) {
[existMap setObject:part forKey:part.partNumber];
}
QCloudLogDebugP(@"Upload",@"SERVER EXIST PARTS %@", [existParts qcloud_modelToJSONString]);
NSMutableArray *restParts = [NSMutableArray new];
for (QCloudFileOffsetBody *offsetBody in allParts) {
NSString *key = [@(offsetBody.index + 1) stringValue];
QCloudMultipartUploadPart *part = [existMap objectForKey:key];
if (!part) {
[restParts addObject:offsetBody];
} else {
if (part.size != offsetBody.sliceLength) {
isChange = YES;
break;
}
QCloudMultipartInfo *info = [QCloudMultipartInfo new];
info.eTag = part.eTag;
info.partNumber = part.partNumber;
[_uploadParts addObject:info];
}
}
if (!isChange) {
if (restParts.count == 0) {
[self finishUpload:self.uploadId];
} else {
[self uploadOffsetBodys:restParts];
}
} else {
//
[self getContinueInfo:existParts.parts];
if (uploadedSize == self.dataContentLength) {
[self finishUpload:self.uploadId];
} else {
//
[self uploadOffsetBodys:[self getFileLocalUploadParts]];
}
}
}
- (void)getContinueInfo:(NSArray *)existParts {
_uploadParts = [NSMutableArray new];
int i = 1;
QCloudMultipartUploadPart *part = existParts[0];
QCloudMultipartInfo *info = [QCloudMultipartInfo new];
info.eTag = part.eTag;
info.partNumber = part.partNumber;
if ([info.partNumber integerValue] != 1) {
return;
}
for (i = 0; i < existParts.count; i++) {
QCloudMultipartUploadPart *part1 = existParts[i];
QCloudMultipartInfo *info1 = [QCloudMultipartInfo new];
info1.eTag = part1.eTag;
info1.partNumber = part1.partNumber;
uploadedSize += part1.size;
[_uploadParts addObject:info1];
if (i == existParts.count - 1) {
break;
}
QCloudMultipartUploadPart *part2 = existParts[i + 1];
if (([part1.partNumber integerValue] + 1) != [part2.partNumber integerValue]) {
break;
}
}
startPartNumber = _uploadParts.count;
QCloudLogDebugP(@"Upload",@"resume startPartNumber = offset = %ld %ld", startPartNumber, uploadedSize);
}
-(void)listParts:(QCloudListPartsResult *)input finish:(void (^_Nullable)(QCloudListPartsResult *_Nullable, NSError *_Nullable))finishBlock{
QCloudListMultipartRequest *request = [QCloudListMultipartRequest new];
request.timeoutInterval = self.timeoutInterval;
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
request.payload = self.payload;
request.object = self.object;
request.regionName = self.regionName;
request.bucket = self.bucket;
request.uploadId = self.uploadId;
request.partNumberMarker = input.nextNumberMarker;
request.retryPolicy.delegate = self;
__weak typeof(request) weakRequest = request;
__weak typeof(self) weakSelf = self;
[request setFinishBlock:^(QCloudListPartsResult *_Nonnull result, NSError *_Nonnull error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (input && input.parts.count > 0 && result && result.parts) {
NSMutableArray * tempParts = input.parts.mutableCopy;
[tempParts addObjectsFromArray:result.parts];
result.parts = tempParts.copy;
}
if (result.nextNumberMarker) {
[self listParts:result finish:finishBlock];
}else{
finishBlock(result,error);
}
}];
[self.transferManager.cosService ListMultipart:request];
}
- (void)resumeUpload {
__weak typeof(self) weakSelf = self;
[self listParts:nil finish:^(QCloudListPartsResult * _Nullable result, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[weakSelf continueMultiUpload:result];
}];
}
- (void)fakeStart {
[self.benchMarkMan benginWithKey:kTaskTookTime];
if (self.uploadId) {
startPartNumber = 0;
uploadedSize = 0;
[self resumeUpload];
return;
}
self.totalBytesSent = 0;
if ([self.body isKindOfClass:[NSData class]]) {
NSData * body = self.body;
if(body.length == 0 && self.transferManager.cosService.configuration.disableUploadZeroData){
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:@"QCloudCOSXMLUploadObjectRequest:InvalidArgument:您输入的bodyData为空并且不允许上传空文件"];
[self onError:error];
[self cancel];
return;
}
[self startSimpleUpload];
} else if ([self.body isKindOfClass:[NSURL class]]) {
NSURL *url = (NSURL *)self.body;
if (!QCloudFileExist(url.relativePath)) {
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid message:@"指定的上传路径不存在"];
[self onError:error];
[self cancel];
return;
}
self.dataContentLength = QCloudFileSize(url.path);
if(_mutilThreshold<kQCloudCOSXMLUploadLengthLimit){
@throw [NSException
exceptionWithName:QCloudErrorDomain
reason:[NSString
stringWithFormat:
@"分块接口的阈值不能小于 1MB ,当前阈值为 %ld", (long)_mutilThreshold]
userInfo:nil];
}
if (self.dataContentLength > _mutilThreshold) {
//0
uploadedSize = 0;
startPartNumber = 0;
[self startMultiUpload];
} else {
if(self.dataContentLength == 0 && self.transferManager.cosService.configuration.disableUploadZeroData){
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:@"QCloudCOSXMLUploadObjectRequest:InvalidArgument:您输入的bodyNSURL:%@)为空并且不允许上传空文件",self.body]];
[self onError:error];
[self cancel];
return;
}
[self startSimpleUpload];
}
} else {
@throw [NSException exceptionWithName:QCloudErrorDomain
reason:@"不支持设置该类型的body支持的类型为NSData、QCloudFileOffsetBody"
userInfo:@{}];
}
}
- (void)startSimpleUpload {
QCloudPutObjectRequest *request = [QCloudPutObjectRequest new];
request.priority = self.uploadPriority;
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
request.regionName = self.regionName;
request.trafficLimit = self.trafficLimit;
request.payload = self.payload;
__weak typeof(self) weakSelf = self;
__weak typeof(request) weakRequest = request;
request.retryPolicy.delegate = self;
request.timeoutInterval = self.timeoutInterval;
request.contentType = self.contentType;
request.finishBlock = ^(id outputObject, NSError *error) {
__strong typeof(weakRequest) strongRequst = weakRequest;
[weakSelf.requstMetricArray addObject:@{ [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (self.requstsMetricArrayBlock) {
self.requstsMetricArrayBlock(weakSelf.requstMetricArray);
}
if (error) {
[weakSelf onError:error];
[self cancel];
} else {
QCloudUploadObjectResult *result = [QCloudUploadObjectResult new];
if (outputObject[@"x-cos-version-id"]) {
result.versionID = outputObject[@"x-cos-version-id"];
}
result.key = weakSelf.object;
result.bucket = weakSelf.bucket;
result.eTag = ((NSDictionary *)outputObject)[@"Etag"];
result.location
= QCloudCOSXMLObjectLocation(weakSelf.transferManager.configuration.endpoint, weakSelf.transferManager.configuration.appID,
weakSelf.bucket, weakSelf.object, self.regionName);
result.__originHTTPURLResponse__ = [outputObject __originHTTPURLResponse__];
result.__originHTTPResponseData__ = [outputObject __originHTTPResponseData__];
if ([outputObject __originHTTPResponseData__]) {
NSData * data = [outputObject __originHTTPResponseData__];
NSHTTPURLResponse * response = [outputObject __originHTTPURLResponse__];
if (response.statusCode == 200) {
NSString *callbackBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
QCloudUploadCallbackResult * callbackResult = [QCloudUploadCallbackResult new];
callbackResult.CallbackBody = callbackBody;
callbackResult.Status = @(response.statusCode).stringValue;
result.CallbackResult = callbackResult;
}
if (response.statusCode == 203 && [response.allHeaderFields[@"Content-Type"] isEqualToString:@"application/xml"]) {
NSError * error;
QCloudXMLDictionaryParser *parser = [QCloudXMLDictionaryParser new];
NSDictionary *params = [parser dictionaryWithData:data];
if (!error && params) {
QCloudUploadCallbackResult * callbackResult = [QCloudUploadCallbackResult new];
callbackResult.Status = @(response.statusCode).stringValue;
QCloudUploadCallbackError * Error = [QCloudUploadCallbackError new];
Error.Code = params[@"Code"];
Error.Message = params[@"Message"];
callbackResult.Error = Error;
result.CallbackResult = callbackResult;
}
}
}
[weakSelf onSuccess:result];
}
};
request.bucket = self.bucket;
request.object = self.object;
request.priority = self.uploadPriority;
request.body = self.body;
request.cacheControl = self.cacheControl;
request.contentDisposition = self.contentDisposition;
request.expect = self.expect;
request.expires = self.expires;
request.contentSHA1 = self.contentSHA1;
request.storageClass = self.storageClass;
request.accessControlList = self.accessControlList;
request.grantRead = self.grantRead;
request.grantFullControl = self.grantFullControl;
request.sendProcessBlock = self.sendProcessBlock;
request.delegate = self.delegate;
request.retryPolicy.delegate = self;
request.customHeaders = [self.customHeaders mutableCopy];
[self.requestCacheArray addPointer:(__bridge void *_Nullable)(request)];
[self.transferManager.cosService PutObject:request];
}
- (void)startMultiUpload {
_uploadParts = [NSMutableArray new];
QCloudInitiateMultipartUploadRequest *uploadRequet = [QCloudInitiateMultipartUploadRequest new];
uploadRequet.timeoutInterval = self.timeoutInterval;
uploadRequet.payload = self.payload;
uploadRequet.enableQuic = self.enableQuic;
uploadRequet.endpoint = self.endpoint;
uploadRequet.networkType = self.networkType;
uploadRequet.bucket = self.bucket;
uploadRequet.regionName = self.regionName;
uploadRequet.object = self.object;
uploadRequet.cacheControl = self.cacheControl;
uploadRequet.contentDisposition = self.contentDisposition;
uploadRequet.expect = self.expect;
uploadRequet.expires = self.expires;
uploadRequet.contentSHA1 = self.contentSHA1;
uploadRequet.storageClass = self.storageClass;
uploadRequet.accessControlList = self.accessControlList;
uploadRequet.grantRead = self.grantRead;
uploadRequet.grantFullControl = self.grantFullControl;
uploadRequet.contentType = self.contentType;
uploadRequet.customHeaders = [self.customHeaders mutableCopy];
uploadRequet.retryPolicy.delegate = self;
__weak typeof(uploadRequet) weakRequest = uploadRequet;
__weak typeof(self) weakSelf = self;
[uploadRequet setFinishBlock:^(QCloudInitiateMultipartUploadResult *_Nonnull result, NSError *_Nonnull error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (error) {
[weakSelf onError:error];
} else {
if (weakSelf.initMultipleUploadFinishBlock) {
self.uploadId = result.uploadId;
QCloudCOSXMLUploadObjectResumeData resumeData = [self productingReqsumeData:nil];
if (self.initMultipleUploadFinishBlock) {
self.initMultipleUploadFinishBlock(result, resumeData);
}
}
[weakSelf uploadMultiParts:result];
}
}];
[self.requestCacheArray addPointer:(__bridge void *_Nullable)(uploadRequet)];
[self.transferManager.cosService InitiateMultipartUpload:uploadRequet];
}
- (NSArray<QCloudFileOffsetBody *> *)getFileLocalUploadParts {
NSMutableArray *allParts = [NSMutableArray new];
if (self.canceled) {
return nil;
}
NSURL *url = (NSURL *)self.body;
if([self.body isKindOfClass:NSURL.class]){
self.dataContentLength = QCloudFileSize(url.relativePath);
}
int64_t restContentLength = self.dataContentLength - uploadedSize;
//便
int64_t offset = uploadedSize;
for (int i = startPartNumber;; i++) {
int64_t slice = 0;
NSUInteger maxSlice = ceil(self.dataContentLength * 1.0 / (10000));
NSUInteger uploadSliceLength = self.sliceSize > 10 ? self.sliceSize : kQCloudCOSXMLUploadSliceLength;
uploadSliceLength = self.dataContentLength * 1.0 / uploadSliceLength > 10000 ? maxSlice : uploadSliceLength;
if (restContentLength >= uploadSliceLength) {
slice = uploadSliceLength;
} else {
slice = restContentLength;
}
if (!_uploadBodyIsCompleted && slice < kQCloudCOSXMLUploadSliceLength) {
break;
}
QCloudFileOffsetBody *body = [[QCloudFileOffsetBody alloc] initWithFile:url offset:offset slice:slice];
[allParts addObject:body];
offset += slice;
body.index = i;
restContentLength -= slice;
if (restContentLength <= 0) {
break;
}
}
return allParts;
}
- (void)appendUploadBytesSent:(int64_t)bytesSent {
[_progressLock lock];
_totalBytesSent += bytesSent;
[self notifySendProgressBytesSend:bytesSent totalBytesSend:_totalBytesSent totalBytesExpectedToSend:_dataContentLength];
[_progressLock unlock];
}
- (void)uploadOffsetBodys:(NSArray<QCloudFileOffsetBody *> *)allParts {
// rest already upload size
int64_t totalTempBytesSend = 0;
for (QCloudFileOffsetBody *body in allParts) {
totalTempBytesSend += body.sliceLength;
}
_totalBytesSent = _dataContentLength - totalTempBytesSend;
[self.benchMarkMan directSetValue:@(totalTempBytesSend) forKey:kTotalSize];
//
__weak typeof(self) weakSelf = self;
_queueSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
__block int totalComplete = 0;
dispatch_source_set_event_handler(_queueSource, ^{
if (weakSelf.queueSource) {
NSUInteger value = dispatch_source_get_data(weakSelf.queueSource);
@synchronized(weakSelf) {
totalComplete += value;
}
if (totalComplete == allParts.count) {
if (NULL != weakSelf.queueSource) {
dispatch_source_cancel(weakSelf.queueSource);
}
[weakSelf finishUpload:weakSelf.uploadId];
}
}
});
dispatch_resume(_queueSource);
for (int i = 0; i < allParts.count; i++) {
__block QCloudFileOffsetBody *body = allParts[i];
//cuploadPartRequest
if (self.canceled) {
QCloudLogDebugP(@"Upload",@"请求被取消终止创建新的uploadPartRequest");
break;
}
QCloudUploadPartRequest *request = [QCloudUploadPartRequest new];
request.enableQuic = self.enableQuic;
request.endpoint = self.endpoint;
request.networkType = self.networkType;
request.payload = self.payload;
request.bucket = self.bucket;
request.trafficLimit = self.trafficLimit;
request.timeoutInterval = self.timeoutInterval;
request.regionName = self.regionName;
request.object = self.object;
request.priority = self.uploadPriority;
request.partNumber = (int)body.index + 1;
request.uploadId = self.uploadId;
request.customHeaders = [self.customHeaders mutableCopy];
request.body = body;
request.retryPolicy.delegate = self;
__weak typeof(request) weakRequest = request;
__block int64_t partBytesSent = 0;
int64_t partSize = body.sliceLength;
[request setSendProcessBlock:^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
BOOL isRetry = weakRequest.isRetry;
if(!weakRequest.enableQuic || !isRetry){
int64_t restSize = totalBytesExpectedToSend - partSize;
if (restSize - partBytesSent <= 0) {
[weakSelf appendUploadBytesSent:bytesSent];
} else {
partBytesSent += bytesSent;
if (restSize - partBytesSent <= 0) {
[weakSelf appendUploadBytesSent:partBytesSent - restSize];
}
}
}
}];
[request setFinishBlock:^(QCloudUploadPartResult *outputObject, NSError *error) {
QCloudLogInfoP(@"Upload",@"收到一个part %d的响应 %@;是否重试:%@", (i + 1), outputObject.eTag, weakRequest.isRetry?@"是":@"否");
if (!weakSelf) {
return;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
@synchronized (self) {
[strongSelf.requstMetricArray addObject:@{ [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
}
if (error && error.code != QCloudNetworkErrorCodeCanceled) {
NSError *transferError = [weakSelf tranformErrorToResume:error];
__strong typeof(weakSelf) strongSelf = weakSelf;
[weakSelf onError:transferError];
if (!self.canceled) {
[strongSelf cancel];
}
}else if(error && error.code == QCloudNetworkErrorCodeCanceled){
if (!self.canceled) {
[strongSelf cancel];
}
} else {
if (self.enableMD5Verification || self.enableVerification) {
if (outputObject.eTag.length == (kQCloudCOSXMLMD5Length + 2)) {
NSString *MD5FromeETag = [outputObject.eTag substringWithRange:NSMakeRange(1, outputObject.eTag.length - 2)];
NSString *localMD5String = [QCloudEncrytFileOffsetMD5(body.fileURL.path, body.offset, body.sliceLength) lowercaseString];
if (![MD5FromeETag isEqualToString:localMD5String]) {
NSMutableString *errorMessageString = [[NSMutableString alloc] init];
[errorMessageString
appendFormat:@"DataIntegrityError分片:上传过程中MD5校验与本地不一致请检查本地文件在上传过程中是否发生了变化,"
@"建议调用删除接口将COS上的文件删除并重新上传,本地计算的 MD5 值:%@, 返回的 ETag值:%@",
localMD5String, MD5FromeETag];
if ([outputObject __originHTTPURLResponse__] &&
[[outputObject __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-request-id"] != nil) {
NSString *requestID = [[outputObject __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-request-id"];
[errorMessageString appendFormat:@", Request id:%@", requestID];
}
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeNotMatch message:errorMessageString];
[weakSelf onError:error];
[weakSelf cancel];
return;
}
}
}
QCloudMultipartInfo *info = [QCloudMultipartInfo new];
info.eTag = outputObject.eTag;
info.partNumber = [@(body.index + 1) stringValue];
[weakSelf markPartFinish:info];
dispatch_source_merge_data(weakSelf.queueSource, 1);
}
}];
[self.requestCacheArray addPointer:(__bridge void *_Nullable)(request)];
[self.transferManager.cosService UploadPart:request];
}
}
- (NSError *)tranformErrorToResume:(NSError *)error {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic addEntriesFromDictionary:error.userInfo];
QCloudCOSXMLUploadObjectResumeData resumeData = [self productingReqsumeData:NULL];
if (resumeData) {
dic[QCloudUploadResumeDataKey] = resumeData;
}
NSError *transferError = [NSError errorWithDomain:error.domain code:error.code userInfo:dic];
transferError.__originHTTPURLResponse__ = error.__originHTTPURLResponse__;
transferError.__originHTTPResponseData__ = error.__originHTTPResponseData__;
return transferError;
}
- (void)uploadMultiParts:(QCloudInitiateMultipartUploadResult *)result {
self.uploadId = result.uploadId;
NSArray *allParts = [self getFileLocalUploadParts];
[self uploadOffsetBodys:allParts];
}
- (void)markPartFinish:(QCloudMultipartInfo *)info {
if (!info) {
return;
}
[_recursiveLock lock];
[_uploadParts addObject:info];
[_recursiveLock unlock];
}
- (void)onError:(NSError *)error {
if (!self.aborted) {
NSError *transferError = [self tranformErrorToResume:error];
[super onError:transferError];
} else {
[super onError:error];
}
}
- (void)finishUpload:(NSString *)uploadId {
NSURL *url = (NSURL *)self.body;
if(self.canceled){
return;
}
if(!self.uploadBodyIsCompleted){
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeImCompleteData
message:@"DataIntegrityError分片:文件大小与原始文件大小不一致,请检查文件在上传的过程中是否发生改变"];
[self onError:error];
return;
}
QCloudCompleteMultipartUploadRequest *complete = [QCloudCompleteMultipartUploadRequest new];
complete.enableQuic = self.enableQuic;
complete.endpoint = self.endpoint;
complete.networkType = self.networkType;
complete.payload = self.payload;
complete.object = self.object;
complete.bucket = self.bucket;
complete.uploadId = self.uploadId;
complete.regionName = self.regionName;
complete.customHeaders = [self.customHeaders mutableCopy];
complete.retryPolicy.delegate = self;
complete.timeoutInterval = self.timeoutInterval;
QCloudCompleteMultipartUploadInfo *info = [QCloudCompleteMultipartUploadInfo new];
[self.uploadParts 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 = self.uploadParts;
complete.parts = info;
__weak typeof(self) weakSelf = self;
__weak typeof(complete) weakRequest = complete;
[complete setFinishBlock:^(QCloudUploadObjectResult *outputObject, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
__strong typeof(weakRequest) strongRequst = weakRequest;
[strongSelf.requstMetricArray addObject:@ { [NSString stringWithFormat:@"%@", strongRequst] : weakRequest.benchMarkMan.tastMetrics }];
if (self.requstsMetricArrayBlock) {
self.requstsMetricArrayBlock(weakSelf.requstMetricArray);
}
if (error) {
[weakSelf onError:error];
} else {
if (nil != outputObject.location) {
outputObject.location
= QCloudFormattHTTPURL(outputObject.location, weakSelf.transferManager.cosService.configuration.endpoint.useHTTPS);
}
if (outputObject.CallbackResult && outputObject.CallbackResult.CallbackBody) {
NSString * callBackBody = outputObject.CallbackResult.CallbackBody;
NSData *data = [[NSData alloc] initWithBase64EncodedString:callBackBody options:0];
NSString *decodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
outputObject.CallbackResult.CallbackBody = decodedString;
}
[weakSelf onSuccess:outputObject];
}
}];
[self.requestCacheArray addPointer:(__bridge void *_Nullable)(complete)];
[self.transferManager.cosService CompleteMultipartUpload:complete];
}
//
+ (instancetype)requestWithRequestData:(QCloudCOSXMLUploadObjectResumeData _Nullable)resumeData {
QCloudCOSXMLUploadObjectRequest *request = [QCloudCOSXMLUploadObjectRequest qcloud_modelWithJSON:resumeData];
QCloudLogDebugP(@"Upload",@"[PROCESS]Generating request from resume data, body is %@", request.body);
QCloudUniversalPath *path = request.body;
// fileURLWithPath
NSString *bodyUrl = QCloudURLDecodeUTF8([path fileURL].absoluteString);
request.body = [NSURL URLWithString:bodyUrl];
QCloudLogDebugP(@"Upload",@"[PROCESS]Path after transfering is %@", request.body);
return request;
}
- (void)cancel {
@synchronized (self) {
[self.requestCacheArray addPointer:(__bridge void *_Nullable)([NSObject new])];
[self.requestCacheArray compact];
}
if (NULL != _queueSource) {
dispatch_source_cancel(_queueSource);
}
NSMutableArray *cancelledRequestIDs = [NSMutableArray array];
NSPointerArray *tmpRequestCacheArray = [self.requestCacheArray copy];
for (QCloudHTTPRequest *request in tmpRequestCacheArray) {
if (request != nil && [request respondsToSelector:@selector(requestID)]) {
[cancelledRequestIDs addObject:[NSNumber numberWithLongLong:request.requestID]];
}
}
[[QCloudHTTPSessionManager shareClient] cancelRequestsWithID:cancelledRequestIDs];
[super cancel];
}
- (QCloudCOSXMLUploadObjectResumeData)cancelByProductingResumeData:(NSError *__autoreleasing *)error {
QCloudLogDebugP(@"Upload",@"cancelByProductingResumeData begin");
[self.requestCacheArray addPointer:(__bridge void *_Nullable)([NSObject new])];
[self.requestCacheArray compact];
//
NSPointerArray *tmpRequestCacheArray = [self.requestCacheArray copy];
// QCloudLogDebug(@"cancel 开始遍历 :[%ld]",tmpRequestCacheArray);
for (QCloudHTTPRequest *request in tmpRequestCacheArray.allObjects) {
if (request.forbidCancelled) {
if (NULL != error) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorUnsupportOperationError
message:@"UnsupportOperation:无法暂停当前的上传请求因为complete请求已经发出"];
}
return nil;
}
}
//cancel
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self cancel];
});
return [self productingReqsumeData:error];
}
+ (nullable NSArray<NSString *> *)modelPropertyBlacklist {
return @[ @"delegate" ];
}
- (QCloudCOSXMLUploadObjectResumeData)productingReqsumeData:(NSError *__autoreleasing *)error {
if (_dataContentLength <= _mutilThreshold) {
if (NULL != error) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorUnsupportOperationError
message:@"UnsupportOperation:无法暂停当前的上传请求,因为使用的是单次上传"];
}
return nil;
}
if (![self.body isKindOfClass:[NSURL class]]) {
if (NULL != error) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorUnsupportOperationError
message:@"UnsupportOperation:无法暂停当前的上传请求,因为使用的是非持久化存储上传"];
}
return nil;
}
if ([self finished]) {
if (NULL != error) {
*error = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeAlreadyFinish
message:@"AlreadyFinished:无法暂停当前的上传请求,因为该请求已经结束"];
}
return nil;
}
[_recursiveLock lock];
NSURL *url = (NSURL *)self.body;
QCloudUniversalPath *universalPath = [QCloudUniversalPathFactory universalPathWithURL:url];
self.body = universalPath;
NSData *info = [self qcloud_modelToJSONData];
QCloudLogDebugP(@"Upload",@"RESUME data %@", info);
self.body = url;
[_recursiveLock unlock];
return info;
}
- (void)abort:(QCloudRequestFinishBlock _Nullable)finishBlock {
if (self.finished) {
NSError *error = [NSError qcloud_errorWithCode:QCloudNetworkErrorUnsupportOperationError message:@"取消失败,任务已经完成"];
if (finishBlock) {
finishBlock(nil, error);
}
} else {
if (self.uploadId) {
QCloudAbortMultipfartUploadRequest *abortRequest = [QCloudAbortMultipfartUploadRequest new];
abortRequest.enableQuic = self.enableQuic;
abortRequest.endpoint = self.endpoint;
abortRequest.networkType = self.networkType;
abortRequest.customHeaders = [self.customHeaders mutableCopy];
abortRequest.object = self.object;
abortRequest.regionName = self.regionName;
abortRequest.bucket = self.bucket;
abortRequest.uploadId = self.uploadId;
abortRequest.finishBlock = finishBlock;
abortRequest.timeoutInterval = self.timeoutInterval;
self.uploadId = nil;
[self.transferManager.cosService AbortMultipfartUpload:abortRequest];
} else {
if (finishBlock) {
finishBlock(@{}, nil);
}
}
}
_aborted = YES;
[self cancel];
}
- (void)setCOSServerSideEncyption {
self.enableMD5Verification = NO;
self.customHeaders[@"x-cos-server-side-encryption"] = @"AES256";
}
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey {
self.enableMD5Verification = NO;
NSData *data = [customerKey dataUsingEncoding:NSUTF8StringEncoding];
NSString *excryptAES256Key = [data base64EncodedStringWithOptions:0]; // base64
NSString *base64md5key = QCloudEncrytNSDataMD5Base64(data);
self.customHeaders[@"x-cos-server-side-encryption-customer-algorithm"] = @"AES256";
self.customHeaders[@"x-cos-server-side-encryption-customer-key"] = excryptAES256Key;
self.customHeaders[@"x-cos-server-side-encryption-customer-key-MD5"] = base64md5key;
}
- (void)setCOSServerSideEncyptionWithKMSCustomKey:(NSString *)customerKey jsonStr:(NSString *)jsonStr {
self.enableMD5Verification = NO;
self.customHeaders[@"x-cos-server-side-encryption"] = @"cos/kms";
if (customerKey) {
self.customHeaders[@"x-cos-server-side-encryption-cos-kms-key-id"] = customerKey;
}
if (jsonStr) {
//stringdata
NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
self.customHeaders[@"x-cos-server-side-encryption-context"] = [data base64EncodedStringWithOptions:0];
}
}
- (BOOL)shouldRetry:(QCloudURLSessionTaskData *)task error:(NSError *)error {
if ([self.retryHandler.delegate respondsToSelector:@selector(shouldRetry:error:)]) {
return [self.retryHandler.delegate shouldRetry:task error:error];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadObjectResult *_Nullable, NSError *_Nullable))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
@end

View File

@@ -0,0 +1,14 @@
//
// QCloudCOSXMLUploadObjectRequest_Private.h
// Pods
//
// Created by Dong Zhao on 2017/5/26.
//
//
#import "QCloudCOSXMLUploadObjectRequest.h"
@class QCloudCOSTransferMangerService;
@interface QCloudCOSXMLUploadObjectRequest ()
@property (nonatomic, weak) QCloudCOSTransferMangerService *transferManager;
@end

View File

@@ -0,0 +1,117 @@
//
// CompleteMultipartUpload.h
// CompleteMultipartUpload
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudUploadObjectResult.h"
@class QCloudCompleteMultipartUploadInfo;
NS_ASSUME_NONNULL_BEGIN
/**
完成整个分块上传的方法.
### 功能描述
当使用分块上传uploadPart(UploadPartRequest))完对象的所有块以后,
必须调用该 completeMultiUpload(CompleteMultiUploadRequest)
或者 completeMultiUploadAsync(CompleteMultiUploadRequest, CosXmlResultListener)
来完成整个文件的分块上传.且在该请求的 Body 中需要给出每一个块的 PartNumber 和 ETag
用来校验块的准确性.
分块上传适合于在弱网络或高带宽环境下上传较大的对象.SDK 支持自行切分对象并分别调用
uploadPart(UploadPartRequest)上传各 个分块.
关于完成整个分片上传接口的描述,请查看 https://cloud.tencent.com/document/product/436/7742.
### 示例
@code
QCloudCompleteMultipartUploadRequest *completeRequst = [QCloudCompleteMultipartUploadRequest new];
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
completeRequst.object = @"exampleobject";
// 存储桶名称,格式为 BucketName-APPID
completeRequst.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 中获取上传结果
}];
[[QCloudCOSXMLService defaultCOSXML] CompleteMultipartUpload:completeRequst];
*/
@interface QCloudCompleteMultipartUploadRequest : QCloudBizHTTPRequest
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
本次分片上传的UploadID
*/
@property (strong, nonatomic) NSString *uploadId;
/**
完成分片上传的信息
*/
@property (strong, nonatomic) QCloudCompleteMultipartUploadInfo *parts;
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,158 @@
//
// CompleteMultipartUpload.m
// CompleteMultipartUpload
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudCompleteMultipartUploadRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudUploadObjectResult.h"
#import "QCloudCompleteMultipartUploadInfo.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudCompleteMultipartUploadRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithXMLParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseXMLSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudUploadObjectResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"post";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (!self.uploadId || ([self.uploadId isKindOfClass:NSString.class] && ((NSString *)self.uploadId).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[uploadId] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setQueryStringParamter:self.uploadId withKey:@"uploadId"];
if (!self.parts) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[parts] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setParameter:[self.parts qcloud_modelToJSONObject] withKey:@"CompleteMultipartUpload"];
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadObjectResult *_Nullable result, NSError *__nullableerror))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:UploadPart"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
- (void)configTaskResume {
self.forbidCancelled = YES;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,43 @@
//
// QCloudGetObjectService.h
// QCloudGetObjectService
//
// Created by tencent
//
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import "QCloudGetObjectRequest.h"
@interface QCloudGetObjectRequest (Custom)
/**
该选项设置为YES后在下载完成后会比对COS上储存的文件MD5和下载到本地的文件MD5
如果MD5有差异的话会返回-340013错误码。
目前默认关闭。
*/
@property (nonatomic, assign) BOOL enableMD5Verification;
@end

View File

@@ -0,0 +1,98 @@
//
// GetObject.m
// GetObject
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudGetObjectRequest+Custom.h"
#import <QCloudCore/QCloudCore.h>
#import <objc/runtime.h>
@interface QCloudBizHTTPRequest ()
- (void)__notifySuccess:(id)object;
@end
@implementation QCloudGetObjectRequest (Custom)
- (void)__notifySuccess:(id)object {
if (!self.enableMD5Verification || ((NSObject *)object).__originHTTPURLResponse__ == nil) {
[super __notifySuccess:object];
return;
}
NSString *MD5FromETag = [((NSObject *)object).__originHTTPURLResponse__ allHeaderFields][@"Etag"];
if (MD5FromETag) {
if ([[MD5FromETag substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"W"]) {
NSRange range = NSMakeRange(3, MD5FromETag.length - 4);
MD5FromETag = [MD5FromETag substringWithRange:range];
} else {
MD5FromETag = [MD5FromETag substringWithRange:NSMakeRange(1, MD5FromETag.length - 2)];
}
}
if ([MD5FromETag containsString:@"-"]) {
[super __notifySuccess:object];
return;
}
NSString *localMD5String;
if (self.downloadingTempURL) {
localMD5String = [QCloudEncrytFileMD5(self.downloadingTempURL.path) lowercaseString];
} else {
if ([object isKindOfClass:[NSData class]]) {
localMD5String = [QCloudEncrytNSDataMD5(object) lowercaseString];
}
}
NSError *resultError;
if (![localMD5String isEqualToString:MD5FromETag]) {
NSMutableString *errorMessageString = [[NSMutableString alloc] init];
[errorMessageString
appendFormat:@"DataIntegrityError:下载过程中MD5校验与本地不一致建议删除文件重新下载, 本地计算的 MD5 值:%@, 返回的 ETag值:%@",
localMD5String, MD5FromETag];
if ([((NSObject *)object).__originHTTPURLResponse__ allHeaderFields][@"x-cos-request-id"] != nil) {
NSString *requestID = [((NSObject *)object).__originHTTPURLResponse__ allHeaderFields][@"x-cos-request-id"];
[errorMessageString appendFormat:@", Request id:%@", requestID];
}
resultError = [NSError qcloud_errorWithCode:QCloudNetworkErrorCodeNotMatch message:errorMessageString];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
self.finishBlock(object, resultError);
});
if ([self.delegate respondsToSelector:@selector(QCloudHTTPRequestDidFinished:succeedWithObject:)]) {
[self.delegate QCloudHTTPRequestDidFinished:self succeedWithObject:object];
}
}
- (BOOL)enableMD5Verification {
NSNumber *number = objc_getAssociatedObject(self, @selector(enableMD5Verification));
return [number boolValue];
}
- (void)setEnableMD5Verification:(BOOL)enableMD5Verification {
NSNumber *number = [NSNumber numberWithBool:enableMD5Verification];
objc_setAssociatedObject(self, @selector(enableMD5Verification), number, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

View File

@@ -0,0 +1,149 @@
//
// GetObject.h
// GetObject
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
下载 COS 对象的方法.
### 功能描述
可以直接发起 GET 请求获取 COS 中完整的对象数据, 或者在 GET 请求 中传入 Range 请求头部获取对象的部分内容.
获取COS 对象的同时,对象的元数据将会作为 HTTP 响应头部随对象内容一同返回COS 支持GET
请求时 使用 URL 参数的方式覆盖响应的部分元数据值,例如覆盖 Content-iDisposition 的响应值.
关于获取 COS 对象的接口描述,请查看 https://cloud.tencent.com/document/product/436/7753.
### 示例
@code
QCloudGetObjectRequest* request = [QCloudGetObjectRequest new];
// 设置下载的路径 URL如果设置了文件将会被下载到指定路径中
// 如果未设置该参数,那么文件将会被下载至内存里,存放在在 finishBlock 的 outputObject 里
request.downloadingURL = [NSURL URLWithString:QCloudTempFilePathWithExtension(@"downding")];
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
request.object = @"exampleobject";
// 存储桶名称,格式为 BucketName-APPID
request.bucket = @"examplebucket-1250000000";
[request setFinishBlock:^(id outputObject, NSError *error) {
// 可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息
NSDictionary* info = (NSDictionary *) outputObject;
}];
[request setDownProcessBlock:^(int64_t bytesDownload, int64_t totalBytesDownload,
int64_t totalBytesExpectedToDownload) {
// 下载过程中的进度
// bytesDownload 一次下载的字节数,
// totalBytesDownload 总过接受的字节数
// totalBytesExpectedToDownload 文件一共多少字节
}];
[[QCloudCOSXMLService defaultCOSXML] GetObject:request];
*/
@interface QCloudGetObjectRequest : QCloudBizHTTPRequest
/**
设置响应头部中的 Content-Type参数
*/
@property (strong, nonatomic) NSString *responseContentType;
/**
设置响应头部中的Content-Language参数
*/
@property (strong, nonatomic) NSString *responseContentLanguage;
/**
设置响应头部中的Content-Expires参数
*/
@property (strong, nonatomic) NSString *responseContentExpires;
/**
设置响应头部中的Cache-Control参数
*/
@property (strong, nonatomic) NSString *responseCacheControl;
/**
设置响应头部中的 Content-Disposition 参数。
*/
@property (strong, nonatomic) NSString *responseContentDisposition;
/**
设置响应头部中的 Content-Encoding 参数。
*/
@property (strong, nonatomic) NSString *responseContentEncoding;
/**
RFC 2616 中定义的指定文件下载范围以字节bytes为单位
*/
@property (strong, nonatomic) NSString *range;
/**
如果文件修改时间晚于指定时间,才返回文件内容。否则返回 412 (not modified)
*/
@property (strong, nonatomic) NSString *ifModifiedSince;
/**
如果文件修改时间早于或等于指定时间,才返回文件内容。否则返回 412 (precondition failed)
*/
@property (strong, nonatomic) NSString *ifUnmodifiedModifiedSince;
/**
当 ETag 与指定的内容一致,才返回文件。否则返回 412 (precondition failed)
*/
@property (strong, nonatomic) NSString *ifMatch;
/**
当 ETag 与指定的内容不一致,才返回文件。否则返回 304 (not modified)
*/
@property (strong, nonatomic) NSString *ifNoneMatch;
/**
指定 Object 的 VersionID (在开启多版本的情况下)
*/
@property (strong, nonatomic) NSString *versionID;
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
给图片添加盲水印
*/
@property (strong, nonatomic) NSString *watermarkRule;
//针对本次下载行流量控制的限速值,必须为数字,单位默认为 bit/s。限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s如果超出该范围将返回400错误
@property (nonatomic, assign) NSInteger trafficLimit;
- (void)setFinishBlock:(void (^_Nullable)(id _Nullable result, NSError *_Nullable error))finishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,208 @@
//
// GetObject.m
// GetObject
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudGetObjectRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudGetObjectRequest+Custom.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudGetObjectRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.objectKeySimplifyCheck = YES;
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[ QCloudURLFuseSimple, QCloudURLFuseWithURLEncodeParamters ];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseAppendHeadersSerializerBlock,
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"get";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (self.objectKeySimplifyCheck && [[self simplifyPath:self.object] isEqualToString:@"/"]) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"The Getobject Key is illegal"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (self.responseContentType) {
[self.requestData setValue:self.responseContentType forHTTPHeaderField:@"response-content-type"];
}
if (self.responseContentLanguage) {
[self.requestData setValue:self.responseContentLanguage forHTTPHeaderField:@"response-content-language"];
}
if (self.responseContentExpires) {
[self.requestData setValue:self.responseContentExpires forHTTPHeaderField:@"response-expires"];
}
if (self.responseCacheControl) {
[self.requestData setValue:self.responseCacheControl forHTTPHeaderField:@"response-cache-control"];
}
if (self.responseContentDisposition) {
[self.requestData setValue:self.responseContentDisposition forHTTPHeaderField:@"response-content-disposition"];
}
if (self.responseContentEncoding) {
[self.requestData setValue:self.responseContentEncoding forHTTPHeaderField:@"response-content-encoding"];
}
if (self.localCacheDownloadOffset) {
self.range = [NSString stringWithFormat:@"bytes=%lld-", self.localCacheDownloadOffset];
}
if (self.range) {
[self.requestData setValue:self.range forHTTPHeaderField:@"Range"];
}
if (self.ifModifiedSince) {
[self.requestData setValue:self.ifModifiedSince forHTTPHeaderField:@"If-Modified-Since"];
}
if (self.ifUnmodifiedModifiedSince) {
[self.requestData setValue:self.ifUnmodifiedModifiedSince forHTTPHeaderField:@"If-Unmodified-Since"];
}
if (self.ifMatch) {
[self.requestData setValue:self.ifMatch forHTTPHeaderField:@"If-Match"];
}
if (self.ifNoneMatch) {
[self.requestData setValue:self.ifNoneMatch forHTTPHeaderField:@"If-None-Match"];
}
if (self.versionID) {
[self.requestData setParameter:self.versionID withKey:@"versionId"];
}
if (self.trafficLimit) {
[self.requestData setValue:@(self.trafficLimit).stringValue forHTTPHeaderField:@"x-cos-traffic-limit"];
}
if(![self.customHeaders isKindOfClass:NSMutableDictionary.class]){
self.customHeaders = self.customHeaders.mutableCopy;
}
[self.customHeaders setObject:@"no-cache" forKey:@"Cache-Control"];
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
if (self.watermarkRule) {
[self.requestData setQueryStringParamter:@"" withKey:self.watermarkRule];
}
if (![self customBuildRequestData:error])
return NO;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (void)setFinishBlock:(void (^_Nullable)(id _Nullable result, NSError *_Nullable error))finishBlock {
if (finishBlock) {
QCloudWeakSelf(self);
[super setFinishBlock:^(id outputObject, NSError *error) {
QCloudStrongSelf(self);
NSError * lError;
if (QCloudFileExist(strongself.downloadingTempURL.relativePath) && !error) {
if (QCloudFileExist(strongself.downloadingURL.relativePath)) {
QCloudRemoveFileByPath(strongself.downloadingURL.relativePath);
}
QCloudMoveFile(strongself.downloadingTempURL.relativePath, strongself.downloadingURL.relativePath, &lError);
}
finishBlock(outputObject,error);
}];
}
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = @"name/cos:GetObject";
NSMutableArray *array = [NSMutableArray array];
[array addObject:dic];
return [array copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,85 @@
//
// HeadObject.h
// HeadObject
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
NS_ASSUME_NONNULL_BEGIN
/**
获取 COS 对象的元数据信息(meta data)的方法.
### 功能描述
获取 COS 对象的元数据信息,需要与 Get 的权限一致.且请求是不返回消息体的.若请求中需要设置If-Modified-Since 头部,
则统一采用 GMT(RFC822) 时间格式例如Tue, 22 Oct 2017 01:35:21 GMT.如果对象不存在,则 返回404.
关于获取 COS 对象的元数据信息接口的具体描述请查看https://cloud.tencent.com/document/product/436/7745.
### 示例
@code
QCloudHeadObjectRequest* headerRequest = [QCloudHeadObjectRequest new];
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
headerRequest.object = @"exampleobject";
// versionId 当启用版本控制时,指定要查询的版本 ID如不指定则查询对象的最新版本
headerRequest.versionID = @"versionID";
// 存储桶名称,格式为 BucketName-APPID
headerRequest.bucket = @"examplebucket-1250000000";
[headerRequest setFinishBlock:^(NSDictionary* result, NSError *error) {
// result 返回具体信息
}];
[[QCloudCOSXMLService defaultCOSXML] HeadObject:headerRequest];
*/
@interface QCloudHeadObjectRequest : QCloudBizHTTPRequest
/**
对象的key
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
如果HEAD指定版本的Object,请在该参数中指定versionID在开启了多版本的情况才有
*/
@property (strong, nonatomic) NSString *versionID;
@property (strong, nonatomic) NSString *ifModifiedSince;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,126 @@
//
// HeadObject.m
// HeadObject
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudHeadObjectRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudHeadObjectRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithURLEncodeParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseAppendHeadersSerializerBlock,
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"head";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
[self.requestData setParameter:self.versionID withKey:@"versionId"];
if (self.ifModifiedSince) {
[self.requestData setValue:self.ifModifiedSince forHTTPHeaderField:@"If-Modified-Since"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = @"name/cos:HeadObject";
NSMutableArray *array = [NSMutableArray array];
[array addObject:dic];
return [array copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,148 @@
//
// InitiateMultipartUpload.h
// InitiateMultipartUpload
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudInitiateMultipartUploadResult.h"
#import "QCloudCOSStorageClassEnum.h"
NS_ASSUME_NONNULL_BEGIN
/**
初始化分块上传的方法.
### 功能描述
使用分块上传对象时,首先要进行初始化分片上传操作,获取对应分块上传的 uploadId用于后续上传操 作.
分块上传适合于在弱网络或高带宽环境下上传较大的对象。
SDK 支持自行切分对象并分别调用uploadPart(UploadPartRequest)
或者uploadPartAsync(UploadPartRequest, CosXmlResultListener)上传各 个分块.
关于初始化分块上传的描述,请查看 https://cloud.tencent.com/document/product/436/7746.
### 示例
@code
QCloudInitiateMultipartUploadRequest* initRequest = [QCloudInitiateMultipartUploadRequest new];
// 存储桶名称,格式为 BucketName-APPID
initRequest.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
initRequest.object = @"exampleobject";
// 将作为对象的元数据返回
initRequest.cacheControl = @"cacheControl";
initRequest.contentDisposition = @"contentDisposition";
// 定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
initRequest.accessControlList = @"public";
// 赋予被授权者读的权限。
initRequest.grantRead = @"grantRead";
// 赋予被授权者写的权限
initRequest.grantWrite = @"grantWrite";
// 赋予被授权者读写权限。 grantFullControl == grantWrite + grantRead
initRequest.grantFullControl = @"grantFullControl";
[initRequest setFinishBlock:^(QCloudInitiateMultipartUploadResult* outputObject,
NSError *error) {
// 获取分块上传的 uploadId后续的上传都需要这个 ID请保存以备后续使用
self->uploadId = outputObject.uploadId;
}];
[[QCloudCOSXMLService defaultCOSXML] InitiateMultipartUpload:initRequest];
*/
@interface QCloudInitiateMultipartUploadRequest : QCloudBizHTTPRequest
/**
对象的名称
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
RFC 2616 中定义的缓存策略,将作为对象的元数据返回
*/
@property (strong, nonatomic) NSString *cacheControl;
/**
RFC 2616 中定义的文件名称,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *contentDisposition;
@property (strong, nonatomic) NSString *expect;
/**
RFC 2616 中定义的文件名称,将作为 Object 元数据保存。
*/
@property (strong, nonatomic) NSString *expires;
@property (strong, nonatomic) NSString *contentSHA1;
@property (strong, nonatomic) NSString *contentType;
/**
设置 Object 的存储级别
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式x-cos-grant-read: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
其中,\<OwnerUin>为根账户的uin而\<SubUin>为子账户的uin使用时替换
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者写的权限。格式x-cos-grant-write: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
其中,\<OwnerUin>为根账户的uin而\<SubUin>为子账户的uin使用时替换
*/
@property (strong, nonatomic) NSString *grantWrite;
/**
赋予被授权者读写权限。格式: id=" ",id=" "
当需要给子账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<SubUin>"
当需要给根账户授权时id="qcs::cam::uin/\<OwnerUin>:uin/\<OwnerUin>"
其中,\<OwnerUin>为根账户的uin而\<SubUin>为子账户的uin使用时替换
*/
@property (strong, nonatomic) NSString *grantFullControl;
- (void)setFinishBlock:(void (^_Nullable)(QCloudInitiateMultipartUploadResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,172 @@
//
// InitiateMultipartUpload.m
// InitiateMultipartUpload
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudInitiateMultipartUploadRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudInitiateMultipartUploadResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudInitiateMultipartUploadRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseURIMethodASURLParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseXMLSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudInitiateMultipartUploadResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"post";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
} else {
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (self.cacheControl) {
[self.requestData setValue:self.cacheControl forHTTPHeaderField:@"Cache-Control"];
}
if (self.contentDisposition) {
[self.requestData setValue:self.contentDisposition forHTTPHeaderField:@"Content-Disposition"];
}
if (self.expect) {
[self.requestData setValue:self.expect forHTTPHeaderField:@"Expect"];
}
if (self.expires) {
[self.requestData setValue:self.expires forHTTPHeaderField:@"Expires"];
}
if (self.contentSHA1) {
[self.requestData setValue:self.contentSHA1 forHTTPHeaderField:@"x-cos-content-sha1"];
}
if (self.contentType) {
[self.requestData setValue:self.contentType forHTTPHeaderField:@"Content-Type"];
}else{
NSString *miniType = detemineFileMemeType(nil, self.object);
[self.requestData setValue:miniType forHTTPHeaderField:@"Content-Type"];
}
if (self.storageClass) {
[self.requestData setValue:QCloudCOSStorageClassTransferToString(self.storageClass) forHTTPHeaderField:@"x-cos-storage-class"];
}
if (self.accessControlList) {
[self.requestData setValue:self.accessControlList forHTTPHeaderField:@"x-cos-acl"];
}
if (self.grantRead) {
[self.requestData setValue:self.grantRead forHTTPHeaderField:@"x-cos-grant-read"];
}
if (self.grantWrite) {
[self.requestData setValue:self.grantWrite forHTTPHeaderField:@"x-cos-grant-write"];
}
if (self.grantFullControl) {
[self.requestData setValue:self.grantFullControl forHTTPHeaderField:@"x-cos-grant-full-control"];
}
self.requestData.URIMethod = @"uploads";
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudInitiateMultipartUploadResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:UploadPart"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,97 @@
//
// ListMultipart.h
// ListMultipart
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudListPartsResult.h"
NS_ASSUME_NONNULL_BEGIN
/**
查询特定分块上传中的已上传的块的方法.
### 功能描述
COS 支持查询特定分块上传中的已上传的块, 即可以 罗列出指定 UploadId 所属的所有已上传成功的分块.
因此,基于此可以完成续传功能.
关于查询特定分块上传中的已上传块接口的描述,请查看 https://cloud.tencent.com/document/product/436/7747.
### 示例
@code
QCloudListBucketMultipartUploadsRequest* uploads = [QCloudListBucketMultipartUploadsRequest new];
// 存储桶名称,格式为 BucketName-APPID
uploads.bucket = @"examplebucket-1250000000";
// 设置最大返回的 multipart 数量,合法取值从 1 到 1000
uploads.maxUploads = 100;
[uploads setFinishBlock:^(QCloudListMultipartUploadsResult* result,
NSError *error) {
// 可以从 result 中返回分块信息
// 进行中的分块上传对象
NSArray<QCloudListMultipartUploadContent*> *uploads = result.uploads;
}];
[[QCloudCOSXMLService defaultCOSXML] ListBucketMultipartUploads:uploads];
*/
@interface QCloudListMultipartRequest : QCloudBizHTTPRequest
/**
对象的名称
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
标识本次分块上传的uploadId
*/
@property (strong, nonatomic) NSString *uploadId;
/**
单次返回最大的条目数量,默认 1000
*/
@property (strong, nonatomic) NSString *maxPartsCount;
/**
默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始
*/
@property (strong, nonatomic) NSString *partNumberMarker;
/**
规定返回值的编码方式
*/
@property (strong, nonatomic) NSString *encodingType;
- (void)setFinishBlock:(void (^_Nullable)(QCloudListPartsResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,152 @@
//
// ListMultipart.m
// ListMultipart
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudListMultipartRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudListPartsResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudListMultipartRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithURLEncodeParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseXMLSerializerBlock,
QCloudResponseAppendHeadersSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudListPartsResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"get";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (!self.uploadId || ([self.uploadId isKindOfClass:NSString.class] && ((NSString *)self.uploadId).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[uploadId] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setParameter:self.uploadId withKey:@"uploadId"];
if (self.maxPartsCount) {
[self.requestData setParameter:self.maxPartsCount withKey:@"max-parts"];
}
if (self.partNumberMarker) {
[self.requestData setParameter:self.partNumberMarker withKey:@"part-number-marker"];
}
if (self.encodingType) {
[self.requestData setParameter:self.encodingType withKey:@"Encoding-Type"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudListPartsResult *_Nullable, NSError *_Nullable))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:UploadPart"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,165 @@
//
// PutObjectCopy.h
// PutObjectCopy
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCopyObjectResult.h"
#import "QCloudCOSStorageClassEnum.h"
NS_ASSUME_NONNULL_BEGIN
/**
简单复制对象的方法.
### 功能描述
COS 中复制对象可以完成如下功能:
创建一个新的对象副本.
复制对象并更名,删除原始对象,实现重命名
修改对象的存储类型,在复制时选择相同的源和目标对象键,修改存储类型.
在不同的腾讯云 COS 地域复制对象.
修改对象的元数据,在复制时选择相同的源和目标对象键,并修改其中的元数据,复制对象时,默认将继承原对象的元数据,
但创建日期将会按新对象的时间计算.
当复制的对象小于等于 5 GB 可以使用简单复制https://cloud.tencent.com/document/product/436/14117).
当复制对象超过 5 GB 时必须使用分块复制https://cloud.tencent.com/document/product/436/14118 来实现复制.
关于简单复制接口的具体描述请查看https://cloud.tencent.com/document/product/436/10881.
### 示例
@code
QCloudPutObjectCopyRequest* request = [[QCloudPutObjectCopyRequest alloc] init];
// 存储桶名称,格式为 BucketName-APPID
request.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
request.object = @"exampleobject";
// 是否拷贝元数据枚举值CopyReplaced默认值 Copy。
// 假如标记为 Copy忽略 Header 中的用户元数据信息直接复制
// 假如标记为 Replaced按 Header 信息修改元数据。当目标路径和原路径一致,即用户试图修改元数据时,必须为 Replaced
request.metadataDirective = @"Copy";
// 定义 Object 的 ACL 属性有效值privatepublic-readdefault。
// 默认值default继承 Bucket 权限)。
// 注意当前访问策略条目限制为1000条如果您无需进行 Object ACL 控制,请填 default
// 或者此项不进行设置,默认继承 Bucket 权限。
request.accessControlList = @"default";
// 源对象所在的路径
request.objectCopySource =
@"sourcebucket-1250000000.cos.ap-guangzhou.myqcloud.com/sourceObject";
// 指定源文件的 versionID只有开启或开启后暂停的存储桶才会响应此参数
request.versionID = @"objectVersion1";
[request setFinishBlock:^(QCloudCopyObjectResult * _Nonnull result,
NSError * _Nonnull error) {
// result 返回具体信息
}];
[[QCloudCOSXMLService defaultCOSXML] PutObjectCopy:request];
*/
@interface QCloudPutObjectCopyRequest : QCloudBizHTTPRequest
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
源文件 URL 路径,可以通过 versionid 子资源指定历史版本
*/
@property (strong, nonatomic) NSString *objectCopySource;
/**
是否拷贝元数据枚举值Copy, Replaced默认值 Copy。假如标记为 Copy忽略 Header 中的用户元数据信息直接复制;
假如标记为 Replaced按 Header 信息修改元数据。当目标路径和原路径一致,即用户试图修改元数据时,必须为 Replaced
*/
@property (strong, nonatomic) NSString *metadataDirective;
/**
当 Object 在指定时间后被修改,则执行操作,否则返回 412。可与 x-cos-copy-source-If-None-Match 一起使用,
与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfModifiedSince;
/**
当 Object 在指定时间后未被修改,则执行操作,否则返回 412。可与 x-cos-copy-source-If-Match 一起使用,
与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfUnmodifiedSince;
/**
当 Object 的 Etag 和给定一致时,则执行操作,否则返回 412。可与x-cos-copy-source-If-Unmodified-Since 一起使用,
与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfMatch;
/**
当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。可与 x-cos-copy-source-If-Modified-Since 一起使用,
与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *objectCopyIfNoneMatch;
/**
对象的存储级别枚举值STANDARDQCloudCOSStorageStandardSTANDARD_IAQCloudCOSStorageStandardIA
默认值STANDARDQCloudCOSStorageStandard
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式x-cos-grant-read: id="[OwnerUin]"
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者写的权限。格式x-cos-grant-write: id="[OwnerUin]"
*/
@property (strong, nonatomic) NSString *grantWrite;
/**
赋予被授权者读写权限。格式:x-cos-grant-full-control: id="[OwnerUin]"
*/
@property (strong, nonatomic) NSString *grantFullControl;
/**
指定源文件的versionID,只有开启或开启后暂停的存储桶,才会响应此参数
*/
@property (strong, nonatomic) NSString *versionID;
- (void)setFinishBlock:(void (^_Nullable)(QCloudCopyObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,185 @@
//
// PutObjectCopy.m
// PutObjectCopy
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudPutObjectCopyRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudCopyObjectResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudPutObjectCopyRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithXMLParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseXMLSerializerBlock,
QCloudResponseAppendHeadersSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudCopyObjectResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"PUT";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (self.objectCopySource) {
[self.requestData setValue:self.objectCopySource forHTTPHeaderField:@"x-cos-copy-source"];
}
if (self.metadataDirective) {
[self.requestData setValue:self.metadataDirective forHTTPHeaderField:@"x-cos-metadata-directive"];
}
if (self.objectCopyIfModifiedSince) {
[self.requestData setValue:self.objectCopyIfModifiedSince forHTTPHeaderField:@"x-cos-copy-source-If-Modified-Since"];
}
if (self.objectCopyIfUnmodifiedSince) {
[self.requestData setValue:self.objectCopyIfUnmodifiedSince forHTTPHeaderField:@"x-cos-copy-source-If-Unmodified-Since"];
}
if (self.objectCopyIfMatch) {
[self.requestData setValue:self.objectCopyIfMatch forHTTPHeaderField:@"x-cos-copy-source-If-Match"];
}
if (self.objectCopyIfNoneMatch) {
[self.requestData setValue:self.objectCopyIfNoneMatch forHTTPHeaderField:@"x-cos-copy-source-If-None-Match"];
}
if (self.storageClass) {
[self.requestData setValue:QCloudCOSStorageClassTransferToString(self.storageClass) forHTTPHeaderField:@"x-cos-storage-class"];
}
if (self.accessControlList) {
[self.requestData setValue:self.accessControlList forHTTPHeaderField:@"x-cos-acl"];
}
if (self.grantRead) {
[self.requestData setValue:self.grantRead forHTTPHeaderField:@"x-cos-grant-read"];
}
if (self.grantWrite) {
[self.requestData setValue:self.grantWrite forHTTPHeaderField:@"x-cos-grant-write"];
}
if (self.grantFullControl) {
[self.requestData setValue:self.grantFullControl forHTTPHeaderField:@"x-cos-grant-full-control"];
}
if (self.versionID) {
[self.requestData setValue:self.versionID forHTTPHeaderField:@"x-cos-version-id"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudCopyObjectResult *_Nullable, NSError *_Nullable))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableDictionary *orginDic = [NSMutableDictionary dictionary];
NSArray *tmpstrsArr = [self.objectCopySource componentsSeparatedByString:@"/"];
NSString *path = @"";
for (int i = 1; i < tmpstrsArr.count; i++) {
if (i == tmpstrsArr.count - 1) {
path = [path stringByAppendingString:tmpstrsArr[i]];
} else {
path = [path stringByAppendingString:tmpstrsArr[i]];
path = [path stringByAppendingString:@"/"];
}
}
NSArray *hostsArray = [tmpstrsArr[1] componentsSeparatedByString:@"."];
orginDic[@"bucket"] = hostsArray[0];
orginDic[@"region"] = hostsArray[2];
orginDic[@"prefix"] = path;
orginDic[@"action"] = @"name/cos:GetObject";
NSMutableDictionary *desDic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
desDic[@"bucket"] = separateArray[0];
desDic[@"region"] = self.runOnService.configuration.endpoint.regionName;
desDic[@"prefix"] = self.object;
desDic[@"action"] = @"name/cos:PutObject";
NSMutableArray *array = [NSMutableArray array];
[array addObject:orginDic];
[array addObject:desDic];
return [array copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// QCloudPutObjectRequest+Custom.h
// Pods-QCloudCOSXMLDemo
//
// Created by karisli(李雪) on 2018/8/14.
//
#import <Foundation/Foundation.h>
#import "QCloudPutObjectRequest.h"
@interface QCloudPutObjectRequest (Custom)
- (void)setCOSServerSideEncyptionWithKMSCustomKey:(NSString *)customerKey jsonStr:(NSString *)jsonStr;
@end

View File

@@ -0,0 +1,32 @@
//
// QCloudPutObjectRequest+Custom.m
// Pods-QCloudCOSXMLDemo
//
// Created by karisli() on 2018/8/14.
//
#import "QCloudPutObjectRequest+Custom.h"
#import <QCloudCore/QCloudCore.h>
#import <objc/runtime.h>
@interface QCloudBizHTTPRequest ()
@end
@implementation QCloudPutObjectRequest (Custom)
- (void)setCOSServerSideEncyptionWithCustomerKey:(NSString *)customerKey {
[super setCOSServerSideEncyptionWithCustomerKey:customerKey];
}
- (void)setCOSServerSideEncyptionWithKMSCustomKey:(NSString *)customerKey jsonStr:(NSString *)jsonStr {
;
self.customHeaders[@"x-cos-server-side-encryption"] = @"cos/kms";
if (customerKey) {
self.customHeaders[@"x-cos-server-side-encryption-cos-kms-key-id"] = customerKey;
}
if (jsonStr) {
//stringdata
NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
self.customHeaders[@"x-cos-server-side-encryption-context"] = [data base64EncodedStringWithOptions:0];
}
}
@end

View File

@@ -0,0 +1,13 @@
//
// QCloudPutObjectRequest+CustomBuild.h
// Pods
//
// Created by Dong Zhao on 2017/5/26.
//
//
#import "QCloudPutObjectRequest.h"
@interface QCloudPutObjectRequest (CustomBuild)
@end

View File

@@ -0,0 +1,16 @@
//
// QCloudPutObjectRequest+CustomBuild.m
// Pods
//
// Created by Dong Zhao on 2017/5/26.
//
//
#import "QCloudPutObjectRequest+CustomBuild.h"
@implementation QCloudPutObjectRequest (CustomBuild)
- (void)onSuccess:(NSDictionary *)object {
[super onSuccess:object];
}
@end

View File

@@ -0,0 +1,134 @@
//
// PutObject.h
// PutObject
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCOSStorageClassEnum.h"
NS_ASSUME_NONNULL_BEGIN
/**
简单上传的方法.
### 功能描述
简单上传主要适用于在单个请求中上传一个小于 5 GB 大小的对象. 对于大于 5 GB 的对象(或者在高带宽或弱网络环境中
)优先使用分片上传的方式 (https://cloud.tencent.com/document/product/436/14112)
关于简单上传接口的具体描述,请查看 https://cloud.tencent.com/document/product/436/7749
### 示例
@code
QCloudPutObjectRequest* put = [QCloudPutObjectRequest new];
// 存储桶名称,格式为 BucketName-APPID
put.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
put.object = @"exampleobject";
put.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];
[put setFinishBlock:^(id outputObject, NSError *error) {
// outputObject 包含所有的响应 http 头部
NSDictionary* info = (NSDictionary *) outputObject;
}];
[[QCloudCOSXMLService defaultCOSXML] PutObject:put];
*/
@interface QCloudPutObjectRequest<BodyType> : QCloudBizHTTPRequest
@property (nonatomic, strong) BodyType body;
/**
对象 名称
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶 名称
*/
@property (strong, nonatomic) NSString *bucket;
/**
RFC 2616 中定义的缓存策略,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *cacheControl;
/**
RFC 2616 中定义用于指示资源的MIME类型将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *contentType;
/**
RFC 2616 中定义的文件名称,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *contentDisposition;
/**
当使用 Expect: 100-continue 时,在收到服务端确认后,才会发送请求内容
*/
@property (strong, nonatomic) NSString *expect;
/**
RFC 2616 中定义的过期时间,将作为 Object 元数据保存
*/
@property (strong, nonatomic) NSString *expires;
@property (strong, nonatomic) NSString *contentSHA1;
/**
对象的存储级别枚举值STANDARDQCloudCOSStorageStandardSTANDARD_IAQCloudCOSStorageStandardIA
ARCHIVEQCloudCOSStorageARCHIVE。默认值STANDARDQCloudCOSStorageStandard
*/
@property (assign, nonatomic) QCloudCOSStorageClass storageClass;
/**
定义 Object 的 ACL 属性。有效值privatepublic-read-writepublic-read默认值private
*/
@property (strong, nonatomic) NSString *accessControlList;
/**
赋予被授权者读的权限。格式id="OwnerUin";
*/
@property (strong, nonatomic) NSString *grantRead;
/**
赋予被授权者写的权限。格式id="OwnerUin";
*/
@property (strong, nonatomic) NSString *grantWrite;
/**
赋予被授权者读写权限。格式: id="OwnerUin";
*/
@property (strong, nonatomic) NSString *grantFullControl;
/**
指定对象对应的Version ID在开启了多版本的情况才有
*/
@property (strong, nonatomic) NSString *versionID;
//针对本次上传进行流量控制的限速值,必须为数字,单位默认为 bit/s。限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s如果超出该范围将返回400错误
@property (nonatomic, assign) NSInteger trafficLimit;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,177 @@
//
// PutObject.m
// PutObject
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudPutObjectRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudPutObjectRequest+Custom.h"
#import <QCloudCore/QCloudFileUtils.h>
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudPutObjectRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseContentMD5Base64StyleHeaders,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseAppendHeadersSerializerBlock,
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"put";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (self.contentType) {
[self.requestData setValue:self.contentType forHTTPHeaderField:@"Content-Type"];
}
if (![self.requestData valueForHttpKey:@"Content-Type"]) {
if ([self.body isKindOfClass:[NSURL class]]) {
NSString *miniType = detemineFileMemeType(self.body, self.object);
[self.requestData setValue:miniType forHTTPHeaderField:@"Content-Type"];
}else{
NSString *miniType = detemineFileMemeType(nil, self.object);
[self.requestData setValue:miniType forHTTPHeaderField:@"Content-Type"];
}
}
if (self.cacheControl) {
[self.requestData setValue:self.cacheControl forHTTPHeaderField:@"Cache-Control"];
}
if (self.contentDisposition) {
[self.requestData setValue:self.contentDisposition forHTTPHeaderField:@"Content-Disposition"];
}
if (self.expect) {
[self.requestData setValue:self.expect forHTTPHeaderField:@"Expect"];
}
if (self.expires) {
[self.requestData setValue:self.expires forHTTPHeaderField:@"Expires"];
}
if (self.contentSHA1) {
[self.requestData setValue:self.contentSHA1 forHTTPHeaderField:@"x-cos-content-sha1"];
}
if (self.storageClass) {
[self.requestData setValue:QCloudCOSStorageClassTransferToString(self.storageClass) forHTTPHeaderField:@"x-cos-storage-class"];
}
if (self.accessControlList) {
[self.requestData setValue:self.accessControlList forHTTPHeaderField:@"x-cos-acl"];
}
if (self.grantRead) {
[self.requestData setValue:self.grantRead forHTTPHeaderField:@"x-cos-grant-read"];
}
if (self.grantWrite) {
[self.requestData setValue:self.grantWrite forHTTPHeaderField:@"x-cos-grant-write"];
}
if (self.grantFullControl) {
[self.requestData setValue:self.grantFullControl forHTTPHeaderField:@"x-cos-grant-full-control"];
}
if (self.versionID) {
[self.requestData setValue:self.versionID forHTTPHeaderField:@"x-cos-version-id"];
}
if (self.trafficLimit) {
[self.requestData setValue:@(self.trafficLimit).stringValue forHTTPHeaderField:@"x-cos-traffic-limit"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
self.requestData.directBody = self.body;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (BOOL)prepareInvokeURLRequest:(NSMutableURLRequest *)urlRequest error:(NSError *__autoreleasing _Nullable *)error{
NSLog(@"%@",urlRequest.URL);
return [super prepareInvokeURLRequest:urlRequest error:error];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = @"name/cos:PutObject";
NSMutableArray *array = [NSMutableArray array];
[array addObject:dic];
return [array copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,148 @@
//
// UploadPartCopy.h
// UploadPartCopy
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudCopyObjectResult.h"
NS_ASSUME_NONNULL_BEGIN
/**
分块复制的方法.
### 功能描述
COS 中复制对象可以完成如下功能:
创建一个新的对象副本.
复制对象并更名,删除原始对象,实现重命名
修改对象的存储类型,在复制时选择相同的源和目标对象键,修改存储类型.
在不同的腾讯云 COS 地域复制对象.
修改对象的元数据,在复制时选择相同的源和目标对象键,并修改其中的元数据,复制对象时,默认将继承原对象的元数据,
但创建日期将会按新对象的时间计算.
当复制的对象小于等于 5 GB 可以使用简单复制https://cloud.tencent.com/document/product/436/14117).
当复制对象超过 5 GB 时必须使用分块复制https://cloud.tencent.com/document/product/436/14118 来实现复制.
关于分块复制接口的具体描述请查看https://cloud.tencent.com/document/product/436/8287.
### 示例
@code
QCloudUploadPartCopyRequest* request = [[QCloudUploadPartCopyRequest alloc] init];
// 存储桶名称,格式为 BucketName-APPID
request.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "dir1/object1"
request.object = @"exampleobject";
// 源文件 URL 路径,可以通过 versionid 子资源指定历史版本
request.source = @"sourcebucket-1250000000.cos.ap-guangzhou.myqcloud.com/sourceObject";
// 在初始化分块上传的响应中会返回一个唯一的描述符upload ID
request.uploadID = uploadId;
// 标志当前分块的序号
request.partNumber = 1;
[request setFinishBlock:^(QCloudCopyObjectResult* result, NSError* error) {
QCloudMultipartInfo *part = [QCloudMultipartInfo new];
// 获取所复制分块的 etag
part.eTag = result.eTag;
part.partNumber = @"1";
// 保存起来用于最后完成上传时使用
self.parts=@[part];
}];
[[QCloudCOSXMLService defaultCOSXML]UploadPartCopy:request];
*/
@interface QCloudUploadPartCopyRequest : QCloudBizHTTPRequest
/**
存储桶名称
*/
@property (strong, nonatomic) NSString *bucket;
/**
对象名
*/
@property (strong, nonatomic) NSString *object;
/**
在初始化分块上传的响应中会返回一个唯一的描述符upload ID
*/
@property (strong, nonatomic) NSString *uploadID;
/**
标志当前分块的序号
*/
@property (assign, nonatomic) int64_t partNumber;
/**
源文件 URL 路径,可以通过 versionid 子资源指定历史版本
*/
@property (strong, nonatomic) NSString *source;
/**
源文件的字节范围,范围值必须使用 bytes=first-last 格式first 和 last 都是基于 0 开始的偏移量。
例如 bytes=0-9 表示你希望拷贝源文件的开头10个字节的数据如果不指定则表示拷贝整个文件。
*/
@property (strong, nonatomic) NSString *sourceRange;
/**
当 Object 在指定时间后被修改,则执行操作,否则返回 412。
可与 x-cos-copy-source-If-None-Match 一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *sourceIfModifiedSince;
/**
当 Object 在指定时间后未被修改,则执行操作,否则返回 412。
可与 x-cos-copy-source-If-Match 一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *sourceIfUnmodifiedSince;
/**
当 Object 的 Etag 和给定一致时,则执行操作,否则返回 412。
可与x-cos-copy-source-If-Unmodified-Since 一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *sourceIfMatch;
/**
当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。
可与 x-cos-copy-source-If-Modified-Since 一起使用,与其他条件联合使用返回冲突。
*/
@property (strong, nonatomic) NSString *sourceIfNoneMatch;
/**
指定 Object 的 Version ID (在开启了多版本的情况下)
*/
@property (strong, nonatomic) NSString *versionID;
- (void)setFinishBlock:(void (^_Nullable)(QCloudCopyObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,188 @@
//
// UploadPartCopy.m
// UploadPartCopy
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudUploadPartCopyRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudCopyObjectResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudUploadPartCopyRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseURIMethodASURLParamters,
QCloudURLFuseWithURLEncodeParamters,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseXMLSerializerBlock,
QCloudResponseAppendHeadersSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudCopyObjectResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"PUT";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setParameter:self.uploadID withKey:@"UploadId"];
[self.requestData setNumberParamter:@(self.partNumber) withKey:@"partNumber"];
if (!self.source || ([self.source isKindOfClass:NSString.class] && ((NSString *)self.source).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[source] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (self.source) {
[self.requestData setValue:self.source forHTTPHeaderField:@"x-cos-copy-source"];
}
if (self.sourceRange) {
[self.requestData setValue:self.sourceRange forHTTPHeaderField:@"x-cos-copy-source-range"];
}
if (self.sourceIfModifiedSince) {
[self.requestData setValue:self.sourceIfModifiedSince forHTTPHeaderField:@"x-cos-copy-source-If-Modified-Since"];
}
if (self.sourceIfUnmodifiedSince) {
[self.requestData setValue:self.sourceIfUnmodifiedSince forHTTPHeaderField:@"x-cos-copy-source-If-Unmodified-Since"];
}
if (self.sourceIfMatch) {
[self.requestData setValue:self.sourceIfMatch forHTTPHeaderField:@"x-cos-copy-source-If-Match"];
}
if (self.sourceIfNoneMatch) {
[self.requestData setValue:self.sourceIfNoneMatch forHTTPHeaderField:@"x-cos-copy-source-If-None-Match"];
}
if (self.versionID) {
[self.requestData setValue:self.versionID forHTTPHeaderField:@"x-cos-version-id"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudCopyObjectResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
NSMutableDictionary *dic = [NSMutableDictionary new];
NSArray *tmpstrsArr = [self.source componentsSeparatedByString:@"/"];
NSString *path = @"";
for (int i = 1; i < tmpstrsArr.count; i++) {
if (i == tmpstrsArr.count - 1) {
path = [path stringByAppendingString:tmpstrsArr[i]];
} else {
path = [path stringByAppendingString:tmpstrsArr[i]];
path = [path stringByAppendingString:@"/"];
}
}
NSArray *hostsArray = [tmpstrsArr[0] componentsSeparatedByString:@"."];
dic[@"bucket"] = hostsArray[0];
dic[@"region"] = hostsArray[2];
dic[@"prefix"] = path;
dic[@"action"] = @"name/cos:GetObject";
[array addObject:dic];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:PutObject"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,36 @@
//
// QCloudUploadPartService.h
// QCloudUploadPartService
//
// Created by tencent
//
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import "QCloudUploadPartRequest.h"
@interface QCloudUploadPartRequest (Custom)
- (BOOL)customBuildRequestData:(NSError *__autoreleasing *)error;
@end

View File

@@ -0,0 +1,41 @@
//
// UploadPart.m
// UploadPart
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudUploadPartRequest+Custom.h"
@implementation QCloudUploadPartRequest (Custom)
- (BOOL)customBuildRequestData:(NSError *__autoreleasing *)error {
if (![super customBuildRequestData:error]) {
return NO;
}
return YES;
}
@end

View File

@@ -0,0 +1,105 @@
//
// UploadPart.h
// UploadPart
//
// Created by tencent
// Copyright (c) 2015年 tencent. All rights reserved.
//
// ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗ ████████╗███████╗██████╗ ███╗ ███╗██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗
// ██████╗
// ██╔═══██╗██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██║████╗ ██║██╔══██╗██║ ██║ ██╔══██╗██╔══██╗
// ██║ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ █████╗ ██████╔╝██╔████╔██║██║██╔██╗ ██║███████║██║ ██║ ███████║██████╔╝
// ██║▄▄ ██║██║ ██║ ██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██╔══██║██║ ██║ ██╔══██║██╔══██╗
// ╚██████╔╝╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║██║ ╚████║██║ ██║███████╗ ███████╗██║
// ██║██████╔╝
// ╚══▀▀═╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═════╝
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import <Foundation/Foundation.h>
#import <QCloudCore/QCloudCore.h>
#import "QCloudUploadPartResult.h"
NS_ASSUME_NONNULL_BEGIN
/**
分块上传文件的方法。
### 功能描述
Upload Part 接口请求实现将对象按照分块的方式上传到 COS。最多支持10000分块每个分块大小为1MB - 5GB最后一个分块可以小于1MB。
关于分块上传文件的接口的描述,请查看 https://cloud.tencent.com/document/product/436/7750.
### 示例
@code
QCloudUploadPartRequest* request = [QCloudUploadPartRequest new];
request.bucket = @"examplebucket-1250000000";
request.object = @"exampleobject";
request.partNumber = 1;
//标识本次分块上传的 ID使用 Initiate Multipart Upload 接口初始化分块上传时会得到一个 uploadId
//该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置
request.uploadId = @"exampleUploadId";
//上传的数据:支持 NSData*NSURL(本地 URL) 和 QCloudFileOffsetBody * 三种类型
request.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];
[request setSendProcessBlock:^(int64_t bytesSent,
int64_t totalBytesSent,
int64_t totalBytesExpectedToSend) {
//上传进度信息
}];
[request setFinishBlock:^(QCloudUploadPartResult* outputObject, NSError *error) {
QCloudMultipartInfo *part = [QCloudMultipartInfo new];
//获取所上传分块的 etag
part.eTag = outputObject.eTag;
part.partNumber = @"1";
// 保存起来用于最好完成上传时使用
self.parts = @[part];
}];
[[QCloudCOSXMLService defaultCOSXML] UploadPart:request];
*/
@interface QCloudUploadPartRequest<BodyType> : QCloudBizHTTPRequest
@property (nonatomic, strong) BodyType body;
/**
对象的名称
*/
@property (strong, nonatomic) NSString *object;
/**
存储桶名
*/
@property (strong, nonatomic) NSString *bucket;
/**
标识本次分块上传的编号
*/
@property (assign, nonatomic) int partNumber;
/**
标识本次分块上传的 ID
使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId
该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置
*/
@property (strong, nonatomic) NSString *uploadId;
@property (strong, nonatomic) NSString *contentSHA1;
@property (strong, nonatomic) NSString *expect;
//针对本次上传进行流量控制的限速值,必须为数字,单位默认为 bit/s。限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s如果超出该范围将返回400错误
@property (nonatomic, assign) NSInteger trafficLimit;
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadPartResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,160 @@
//
// UploadPart.m
// UploadPart
//
// Created by tencent
// Copyright (c) 2015 tencent. All rights reserved.
//
//
//
//
//
//
//
//
//
//
//
// _ __ _ _
// (_) / _| | | | |
// ___ ___ _ ____ ___ ___ ___ | |_ ___ _ __ __| | _____ _____| | ___ _ __ ___ _
// __ ___
// / __|/ _ \ '__\ \ / / |/ __/ _ \ | _/ _ \| '__| / _` |/ _ \ \ / / _ \ |/ _ \| '_ \ / _ \
// '__/ __|
// \__ \ __/ | \ V /| | (_| __/ | || (_) | | | (_| | __/\ V / __/ | (_) | |_) | __/
// | \__
// |___/\___|_| \_/ |_|\___\___| |_| \___/|_| \__,_|\___| \_/ \___|_|\___/| .__/
// \___|_| |___/
// ______ ______ ______ ______ ______ ______ ______ ______ | |
// |______|______|______|______|______|______|______|______| |_|
//
#import "QCloudUploadPartRequest.h"
#import <QCloudCore/QCloudSignatureFields.h>
#import <QCloudCore/QCloudCore.h>
#import <QCloudCore/QCloudConfiguration_Private.h>
#import "QCloudUploadPartRequest+Custom.h"
#import "QCloudUploadPartResult.h"
NS_ASSUME_NONNULL_BEGIN
@implementation QCloudUploadPartRequest
- (void)dealloc {
}
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}
- (void)configureReuqestSerializer:(QCloudRequestSerializer *)requestSerializer responseSerializer:(QCloudResponseSerializer *)responseSerializer {
NSArray *customRequestSerilizers = @[
QCloudURLFuseSimple,
QCloudURLFuseWithURLEncodeParamters,
QCloudURLFuseContentMD5Base64StyleHeaders,
];
NSArray *responseSerializers = @[
QCloudAcceptRespnseCodeBlock([NSSet setWithObjects:@(200), @(201), @(202), @(203), @(204), @(205), @(206), @(207), @(208), @(226), nil], nil),
QCloudResponseAppendHeadersSerializerBlock,
QCloudResponseObjectSerilizerBlock([QCloudUploadPartResult class])
];
[requestSerializer setSerializerBlocks:customRequestSerilizers];
[responseSerializer setSerializerBlocks:responseSerializers];
requestSerializer.HTTPMethod = @"put";
}
- (BOOL)buildRequestData:(NSError *__autoreleasing *)error {
if (![super buildRequestData:error]) {
return NO;
}
if (!self.object || ([self.object isKindOfClass:NSString.class] && ((NSString *)self.object).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[object] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
if (!self.bucket || ([self.bucket isKindOfClass:NSString.class] && ((NSString *)self.bucket).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[bucket] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
NSURL *__serverURL = [self.runOnService.configuration.endpoint serverURLWithBucket:self.bucket
appID:self.runOnService.configuration.appID
regionName:self.regionName];
self.requestData.serverURL = __serverURL.absoluteString;
[self.requestData setValue:__serverURL.host forHTTPHeaderField:@"Host"];
[self.requestData setNumberParamter:@(self.partNumber) withKey:@"partNumber"];
if (!self.uploadId || ([self.uploadId isKindOfClass:NSString.class] && ((NSString *)self.uploadId).length == 0)) {
if (error != NULL) {
*error = [NSError
qcloud_errorWithCode:QCloudNetworkErrorCodeParamterInvalid
message:[NSString stringWithFormat:
@"InvalidArgument:paramter[uploadId] is invalid (nil), it must have some value. please check it"]];
return NO;
}
}
[self.requestData setParameter:self.uploadId withKey:@"uploadId"];
if (self.contentSHA1) {
[self.requestData setValue:self.contentSHA1 forHTTPHeaderField:@"x-cos-content-sha1"];
}
if (self.expect) {
[self.requestData setValue:self.expect forHTTPHeaderField:@"Expect"];
}
if (self.trafficLimit) {
[self.requestData setValue:@(self.trafficLimit).stringValue forHTTPHeaderField:@"x-cos-traffic-limit"];
}
NSMutableArray *__pathComponents = [NSMutableArray arrayWithArray:self.requestData.URIComponents];
if (self.object)
[__pathComponents addObject:self.object];
self.requestData.URIComponents = __pathComponents;
if (![self customBuildRequestData:error])
return NO;
self.requestData.directBody = self.body;
for (NSString *key in self.customHeaders.allKeys.copy) {
[self.requestData setValue:self.customHeaders[key] forHTTPHeaderField:key];
}
return YES;
}
- (void)setFinishBlock:(void (^_Nullable)(QCloudUploadPartResult *_Nullable result, NSError *_Nullable error))QCloudRequestFinishBlock {
[super setFinishBlock:QCloudRequestFinishBlock];
}
- (QCloudSignatureFields *)signatureFields {
QCloudSignatureFields *fileds = [QCloudSignatureFields new];
return fileds;
}
- (NSArray<NSMutableDictionary *> *)scopesArray {
NSMutableArray *array = [NSMutableArray array];
[array addObject:[self getScopeWithAction:@"name/cos:InitiateMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:ListParts"]];
[array addObject:[self getScopeWithAction:@"name/cos:UploadPart"]];
[array addObject:[self getScopeWithAction:@"name/cos:CompleteMultipartUpload"]];
[array addObject:[self getScopeWithAction:@"name/cos:AbortMultipartUpload"]];
return [array copy];
}
- (NSMutableDictionary *)getScopeWithAction:(NSString *)action {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSArray *separatetmpArray = [self.requestData.serverURL componentsSeparatedByString:@"://"];
NSString *str = separatetmpArray[1];
NSArray *separateArray = [str componentsSeparatedByString:@"."];
dic[@"bucket"] = separateArray[0];
dic[@"region"] = self.runOnService.configuration.endpoint.regionName;
dic[@"prefix"] = self.object;
dic[@"action"] = action;
return dic;
}
@end
NS_ASSUME_NONNULL_END

126
Pods/QCloudCOSXML/README.md generated Normal file
View File

@@ -0,0 +1,126 @@
# 腾讯云 存储SDK for iOS
![XCTest](https://github.com/tencentyun/qcloud-sdk-ios/workflows/XCTest/badge.svg)
## 前言
您可以在新建项目配置好SDK或者在已有的项目中集成进SDK或者先运行下Demo感受下SDK是如何运作的。下载Demo体验请前点击[Demo下载地址](https://github.com/tencentyun/qcloud-sdk-ios-samples.git)。
使用我们的SDK前您需要配置好开发环境
- Xcode 7 或更新的版本
- 运行环境为 iOS 8 以上
本仓库中只包含了SDK的代码和docset格式的文档。如果需要更多的信息可以浏览腾讯云官网。具体SDK的文档在对应目录下的REAME.md中。
## 产品列表
当前仓库内提供的产品有:
- 基于 COS JSON API 封装的 SDK
- 基于 COS XML API 封装的 SDK
## xcframework 支持
提供xcframework打包脚本可以自行打包。
克隆本仓库到本地。
执行以下命令:
```
chmod +x xcframework_build.sh
source xcframework_build.sh
```
### framework 说明:
* QCloudCore.xcframework 和 QCloudCOSXML.xcframework 为COS SDK核心组件必须添加到项目中。
* QCloudTrack.xcframework、COSBeaconAPI_Base.xcframework.zip、QimeiSDK.xcframework.zip 为日志上报组件,与 COS 上传下载功能无关,可选使用。
执行结束后,可在仓库根目录看到 xcframework文件夹。
## 集成SDK
您可以通过Cocoapods集成、下载源代码或者使用我们打包好的动态库来进行SDK的集成工作。在这里我们推荐您使用Cocoapods的方式来进行集成。在您的podfile中加入需要集成的库即可。
如果需要使用基于XML封装的SDK:
```
pod 'QCloudCOSXML'
```
如果需要使用基于V4封装的重构后的SDK:
```
pod 'QCloudNewCOSV4'
```
其他的具体的集成方式进入该SDK所在的文件夹中查看README可以详见具体库的文档。
## 接口说明
SDK 包含的 COS 接口说明请查看官网的 [iOS 接口文档](https://cloud.tencent.com/document/product/436/11280)。
## 文档集成
我们提供了docset格式的文档在仓库的Documents目录中或者可以从release中下载。您可以直接使用Dash来打开。也可以将文档集成到Xcode中去。
### 集成文档到Xcode
您只需要docset格式的文档移动至 ~/Library/Developer/Shared/Documentation/DocSets文件夹中然后重启Xcode即可将文档安装至Xcode中。安装成功后可以在Xcode的Help-Documentation and API Reference中查看。您也可以使用命令行完成这一过程
```
$ cd docset所在路径
```
```
$ mkdir -p ~/Library/Developer/Shared/Documentation/DocSets
```
```
$ mv com.tencent.qcloudcosxml.ios.docset ~/Library/Developer/Shared/Documentation/DocSets
```
## iOS9适配
我们的SDK是运行在HTTP上的。由于iOS9之后苹果引入App Transport Security (ATS)特性集成SDK的APP需要一些额外的步骤来适配iOS9和以上的系统。
在集成SDK的APP的info.plist中需要添加如下代码
```
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>myqcloud.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
```
## 日志
默认情况下SDK内部的日志并不会直接输出到控制台中。在Debug等情况下需要查看日志的话可以设置对应的环境变量开启。开启的具体方式为在Xcode左上角选择点击当前的target-Edit Scheme-在Enviriments Variables中填入QCloudLogLevel这个环境变量如果需要输出所有debug信息那么将值设置为6。
![](http://picturebad-1253653367.coscd.myqcloud.com/134C210F-6682-4BDF-A801-E146263150D0.png)
为了方便排查问题以及查看SDK日志在app启动时会检测剪贴板字符串是否为“##qcloud-cos-log-ispct##”如果是不会对字符串本身进行任何操作则会弹出日志alert进行日志查看以及上传
也可以手动关闭此功能
```
[QCloudLogManager sharedInstance].shouldShowLog = NO;
```
## 代码块 Code Snippet
为了提升用户体验和减少出错的概率,对于一些常见的接口我们提供了 XCode 中可以使用的代码块,将这些代码块集成进 XCode 以后,可以直接调用代码块来填充代码,减少重复的工作量。
集成方式: 将 CodeSnippets 文件夹下,所需要的代码块文件(以.codesnippet结尾)复制到以下文件夹中可以在Finder里按 Command+Shift+G填入路径跳转
```
~/Library/Developer/Xcode/UserData/CodeSnippets
```
集成后,重启 XCode ,并且输入快捷方式(例如 cos ),即可弹出对应的填充选项,直接填充完成该操作所需的基本代码, 按回车直接填充。
![](http://imagebad-1253653367.cosgz.myqcloud.com/code-snippet.png )
## License
Tencent Cloud SDK for iOS and samples are released under the MIT license.
~~~
Copyright (c) 2017 腾讯云
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
~~~

View File

@@ -0,0 +1,18 @@
//
// QCloudThreadSafeMutableDictionary.h
// Pods
//
// Created by Dong Zhao on 2017/3/31.
//
//
#import <Foundation/Foundation.h>
@interface QCloudThreadSafeMutableDictionary : NSObject
- (id)objectForKey:(id)aKey;
- (void)removeObjectForKey:(id)aKey;
- (void)removeObject:(id)object;
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey;
- (NSArray *)allKeys;
- (NSArray *)allValues;
@end

View File

@@ -0,0 +1,78 @@
//
// QCloudThreadSafeMutableDictionary.m
// Pods
//
// Created by Dong Zhao on 2017/3/31.
//
//
#import "QCloudThreadSafeMutableDictionary.h"
@interface QCloudThreadSafeMutableDictionary ()
@property (nonatomic, strong) NSMutableDictionary *dictionary;
@property (nonatomic, strong) dispatch_queue_t dispatchQueue;
@end
@implementation QCloudThreadSafeMutableDictionary
- (instancetype)init {
if (self = [super init]) {
_dictionary = [NSMutableDictionary new];
_dispatchQueue = dispatch_queue_create("com.tencent.qcloud.safedicationary", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (id)objectForKey:(id)aKey {
__block id returnObject = nil;
dispatch_sync(self.dispatchQueue, ^{
returnObject = [self.dictionary objectForKey:aKey];
});
return returnObject;
}
- (void)removeObjectForKey:(id)aKey {
dispatch_sync(self.dispatchQueue, ^{
[self.dictionary removeObjectForKey:aKey];
});
}
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
dispatch_sync(self.dispatchQueue, ^{
[self.dictionary setObject:anObject forKey:aKey];
});
}
- (NSArray *)allKeys {
__block NSArray *allKeys = nil;
dispatch_sync(self.dispatchQueue, ^{
allKeys = [self.dictionary allKeys];
});
return allKeys;
}
- (NSArray *)allValues {
__block NSArray *allValues = nil;
dispatch_sync(self.dispatchQueue, ^{
allValues = [self.dictionary allValues];
});
return allValues;
}
- (void)removeObject:(id)object {
dispatch_sync(self.dispatchQueue, ^{
for (NSString *key in self.dictionary) {
if (object == self.dictionary[key]) {
[self.dictionary removeObjectForKey:key];
break;
}
}
});
}
@end

View File

@@ -0,0 +1,23 @@
//
// QCloudCustomLoader.h
// Pods
//
// Created by garenwang on 2024/12/30.
//
#import <Foundation/Foundation.h>
#import "QCloudCustomSession.h"
#import "QCloudCustomLoaderTask.h"
#import "QCloudHTTPRequest.h"
NS_ASSUME_NONNULL_BEGIN
@protocol QCloudCustomLoader <NSObject>
-(QCloudCustomSession *)session;
-(BOOL)enable:(QCloudHTTPRequest *)httpRequest;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,35 @@
//
// QCloudCustomLoaderTask.h
// Pods-QCloudCOSXMLDemo
//
// Created by garenwang on 2024/12/26.
//
#import <Foundation/Foundation.h>
@class QCloudCustomSession;
NS_ASSUME_NONNULL_BEGIN
@interface QCloudCustomLoaderTask : NSURLSessionDataTask
@property (nullable, readwrite, copy) NSHTTPURLResponse *response;
@property (nullable, readwrite, copy) NSURLRequest *currentRequest;
@property (nullable, readwrite, copy) NSURLRequest *originalRequest;
@property (atomic, assign) int64_t countOfBytesSent;
@property (atomic, assign) int64_t countOfBytesExpectedToSend;
/// 子类实现用于构建自定义task。
/// - Parameters:
/// - httpRequest: SDK 构建好的 NSMutableURLRequest示例对象。
/// - fromFile: 上传文件的本地路径,只有上传文件格式为文件路径时才有值。
/// - session: 自定义session QCloudCustomSession的子类实例。
- (instancetype)initWithHTTPRequest:(NSMutableURLRequest *)httpRequest
fromFile:(NSURL *)fromFile
session:(QCloudCustomSession *)session;
/// 子类实现,用于开启任务。
-(void)resume;
/// 子类实现,用于取消当前任务。
- (void)cancel;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,37 @@
//
// QCloudCustomLoaderTask.m
// Pods-QCloudCOSXMLDemo
//
// Created by garenwang on 2024/12/26.
//
#import "QCloudCustomLoaderTask.h"
#import "QCloudCustomSession.h"
#import "QCloudError.h"
@interface QCloudCustomLoaderTask ()
@property (nonatomic,strong)NSMutableURLRequest * httpRequest;
@property (nonatomic,strong)QCloudCustomSession * session;
@end
@implementation QCloudCustomLoaderTask
@synthesize response = _response;
@synthesize originalRequest = _originalRequest;
@synthesize currentRequest = _currentRequest;
@synthesize countOfBytesSent = _countOfBytesSent;
@synthesize countOfBytesExpectedToSend = _countOfBytesExpectedToSend;
- (instancetype)initWithHTTPRequest:(NSMutableURLRequest *)httpRequest
fromFile:(NSURL *)fromFile
session:(QCloudCustomSession *)session{
@throw [NSException exceptionWithName:QCloudErrorDomain reason:@"请在子类中实现" userInfo:nil];
}
-(void)resume{
@throw [NSException exceptionWithName:QCloudErrorDomain reason:@"请在子类中实现" userInfo:nil];
}
- (void)cancel{
@throw [NSException exceptionWithName:QCloudErrorDomain reason:@"请在子类中实现" userInfo:nil];
}
@end

View File

@@ -0,0 +1,91 @@
//
// QCloudCustomSession.h
// Pods-QCloudCOSXMLDemo
//
// Created by garenwang on 2024/12/26.
//
#import <Foundation/Foundation.h>
@class QCloudCustomLoaderTask;
NS_ASSUME_NONNULL_BEGIN
@interface QCloudCustomSession : NSURLSession
@property (nonatomic,
weak)id<NSURLSessionTaskDelegate, NSURLSessionDataDelegate>customDelegate;
/// 需要子类实现由COS SDK 进行回调。
/// - Parameters:
/// - request: SDK 传出来的请求实例。
/// - fromFile: 以文件路径进行上传时的本地文件路径。
-(QCloudCustomLoaderTask *)taskWithRequset:(NSMutableURLRequest *)request
fromFile:(NSURL *)fromFile;
/// 以下方法无需子类实现。供业务层调用用于将自定义网络相应数据传给COS SDK。
/******************************************************************************/
/// 处理数据任务接收到响应时的情况
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - response:请求响应数据
/// - completionHandler: 完成回调
- (void)customTask:(QCloudCustomLoaderTask *)task didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler;
/// 监控上传任务的进度
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - bytesSent: 当前发送数据
/// - totalBytesSent: 总共发送数据
/// - totalBytesExpectedToSend: 总共待发送数据
- (void)customTask:(QCloudCustomLoaderTask *)task didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;
/// 接受到数据
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - data: 接受到的数据
- (void)customTask:(QCloudCustomLoaderTask *)task didReceiveData:(NSData *)data;
/// 任务完成
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - error: 错误信息, SDK内会根据error 中的错误信息判断是否需要重试。
- (void)customTask:(QCloudCustomLoaderTask *)task didCompleteWithError:(NSError *)error;
/// 处理身份验证
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - challenge: NSURLAuthenticationChallenge
/// - completionHandler: 完成回调
- (void)customTask:(QCloudCustomLoaderTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *_Nonnull)challenge
completionHandler:(void (^_Nonnull)(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *_Nullable credential))completionHandler;
/// 收集性能参数
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - metrics: NSURLSessionTaskMetrics 请求性能参数
- (void)customTask:(QCloudCustomLoaderTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(ios(10.0));
/// 处理重定向
/// - Parameters:
/// - task: 自定义Task QCloudCustomLoaderTask子类
/// - response: 请求响应
/// - request: 重定向的请求
/// - completionHandler: 完成回调
- (void)customTask:(QCloudCustomLoaderTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More