QNBaseUpload.m 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. //
  2. // QNBaseUpload.m
  3. // QiniuSDK
  4. //
  5. // Created by WorkSpace_Sun on 2020/4/19.
  6. // Copyright © 2020 Qiniu. All rights reserved.
  7. //
  8. #import "QNZoneInfo.h"
  9. #import "QNResponseInfo.h"
  10. #import "QNDefine.h"
  11. #import "QNBaseUpload.h"
  12. #import "QNUploadDomainRegion.h"
  13. @interface QNBaseUpload ()
  14. @property (nonatomic, strong) QNBaseUpload *strongSelf;
  15. @property (nonatomic, copy) NSString *key;
  16. @property (nonatomic, copy) NSString *fileName;
  17. @property (nonatomic, strong) NSData *data;
  18. @property (nonatomic, strong) id <QNFileDelegate> file;
  19. @property (nonatomic, strong) QNUpToken *token;
  20. @property (nonatomic, copy) NSString *identifier;
  21. @property (nonatomic, strong) QNUploadOption *option;
  22. @property (nonatomic, strong) QNConfiguration *config;
  23. @property (nonatomic, strong) id <QNRecorderDelegate> recorder;
  24. @property (nonatomic, copy) NSString *recorderKey;
  25. @property (nonatomic, strong) QNUpTaskCompletionHandler completionHandler;
  26. @property (nonatomic, assign)NSInteger currentRegionIndex;
  27. @property (nonatomic, strong)NSMutableArray <id <QNUploadRegion> > *regions;
  28. @property (nonatomic, strong)QNUploadRegionRequestMetrics *currentRegionRequestMetrics;
  29. @end
  30. @implementation QNBaseUpload
  31. - (instancetype)initWithFile:(id<QNFileDelegate>)file
  32. key:(NSString *)key
  33. token:(QNUpToken *)token
  34. option:(QNUploadOption *)option
  35. configuration:(QNConfiguration *)config
  36. recorder:(id<QNRecorderDelegate>)recorder
  37. recorderKey:(NSString *)recorderKey
  38. completionHandler:(QNUpTaskCompletionHandler)completionHandler{
  39. return [self initWithFile:file data:nil fileName:[[file path] lastPathComponent] key:key token:token option:option configuration:config recorder:recorder recorderKey:recorderKey completionHandler:completionHandler];
  40. }
  41. - (instancetype)initWithData:(NSData *)data
  42. key:(NSString *)key
  43. fileName:(NSString *)fileName
  44. token:(QNUpToken *)token
  45. option:(QNUploadOption *)option
  46. configuration:(QNConfiguration *)config
  47. completionHandler:(QNUpTaskCompletionHandler)completionHandler{
  48. return [self initWithFile:nil data:data fileName:fileName key:key token:token option:option configuration:config recorder:nil recorderKey:nil completionHandler:completionHandler];
  49. }
  50. - (instancetype)initWithFile:(id<QNFileDelegate>)file
  51. data:(NSData *)data
  52. fileName:(NSString *)fileName
  53. key:(NSString *)key
  54. token:(QNUpToken *)token
  55. option:(QNUploadOption *)option
  56. configuration:(QNConfiguration *)config
  57. recorder:(id<QNRecorderDelegate>)recorder
  58. recorderKey:(NSString *)recorderKey
  59. completionHandler:(QNUpTaskCompletionHandler)completionHandler{
  60. if (self = [super init]) {
  61. _file = file;
  62. _data = data;
  63. _fileName = fileName ?: @"?";
  64. _key = key;
  65. _token = token;
  66. _config = config;
  67. _option = option ?: [QNUploadOption defaultOptions];
  68. _recorder = recorder;
  69. _recorderKey = recorderKey;
  70. _completionHandler = completionHandler;
  71. [self initData];
  72. }
  73. return self;
  74. }
  75. - (instancetype)init{
  76. if (self = [super init]) {
  77. [self initData];
  78. }
  79. return self;
  80. }
  81. - (void)initData{
  82. _strongSelf = self;
  83. _currentRegionIndex = 0;
  84. _metrics = [QNUploadTaskMetrics emptyMetrics];
  85. }
  86. - (void)run {
  87. kQNWeakSelf;
  88. [_config.zone preQuery:self.token on:^(int code, QNResponseInfo *responseInfo, QNUploadRegionRequestMetrics *metrics) {
  89. kQNStrongSelf;
  90. [self.metrics addMetrics:metrics];
  91. if (code == 0) {
  92. int prepareCode = [self prepareToUpload];
  93. if (prepareCode == 0) {
  94. [self startToUpload];
  95. } else {
  96. QNResponseInfo *responseInfoP = [QNResponseInfo errorResponseInfo:prepareCode errorDesc:nil];
  97. [self complete:responseInfoP response:responseInfoP.responseDictionary];
  98. }
  99. } else {
  100. [self complete:responseInfo response:responseInfo.responseDictionary];
  101. }
  102. }];
  103. }
  104. - (int)prepareToUpload{
  105. int ret = 0;
  106. if (![self setupRegions]) {
  107. ret = -1;
  108. }
  109. return ret;
  110. }
  111. - (void)startToUpload{
  112. }
  113. - (BOOL)switchRegionAndUpload{
  114. if (self.currentRegionRequestMetrics) {
  115. [self.metrics addMetrics:self.currentRegionRequestMetrics];
  116. self.currentRegionRequestMetrics = nil;
  117. }
  118. BOOL isSwitched = [self switchRegion];
  119. if (isSwitched) {
  120. [self startToUpload];
  121. }
  122. return isSwitched;
  123. }
  124. // 根据错误信息进行切换region并上传,return:是否切换region并上传
  125. - (BOOL)switchRegionAndUploadIfNeededWithErrorResponse:(QNResponseInfo *)errorResponseInfo {
  126. if (!errorResponseInfo || errorResponseInfo.isOK || // 不存在 || 不是error 不切
  127. !errorResponseInfo.couldRetry || ![self.config allowBackupHost] || // 不能重试不切
  128. ![self switchRegionAndUpload]) { // 切换失败
  129. return NO;
  130. }
  131. return YES;
  132. }
  133. - (void)complete:(QNResponseInfo *)info
  134. response:(NSDictionary *)response{
  135. if (self.currentRegionRequestMetrics) {
  136. [self.metrics addMetrics:self.currentRegionRequestMetrics];
  137. }
  138. if (self.completionHandler) {
  139. self.completionHandler(info, _key, _metrics, response);
  140. }
  141. self.strongSelf = nil;
  142. }
  143. //MARK:-- region
  144. - (BOOL)setupRegions{
  145. NSMutableArray *defaultRegions = [NSMutableArray array];
  146. NSArray *zoneInfos = [self.config.zone getZonesInfoWithToken:self.token].zonesInfo;
  147. for (QNZoneInfo *zoneInfo in zoneInfos) {
  148. QNUploadDomainRegion *region = [[QNUploadDomainRegion alloc] init];
  149. [region setupRegionData:zoneInfo];
  150. if (region.isValid) {
  151. [defaultRegions addObject:region];
  152. }
  153. }
  154. self.regions = defaultRegions;
  155. self.metrics.regions = defaultRegions;
  156. return defaultRegions.count > 0;
  157. }
  158. - (void)insertRegionAtFirst:(id <QNUploadRegion>)region{
  159. BOOL hasRegion = NO;
  160. for (id <QNUploadRegion> regionP in self.regions) {
  161. if ([regionP.zoneInfo.regionId isEqualToString:region.zoneInfo.regionId]) {
  162. hasRegion = YES;
  163. break;
  164. }
  165. }
  166. if (!hasRegion) {
  167. [self.regions insertObject:region atIndex:0];
  168. }
  169. }
  170. - (BOOL)switchRegion{
  171. BOOL ret = NO;
  172. @synchronized (self) {
  173. NSInteger regionIndex = _currentRegionIndex + 1;
  174. if (regionIndex < self.regions.count) {
  175. _currentRegionIndex = regionIndex;
  176. ret = YES;
  177. }
  178. }
  179. return ret;
  180. }
  181. - (id <QNUploadRegion>)getTargetRegion{
  182. return self.regions.firstObject;
  183. }
  184. - (id <QNUploadRegion>)getCurrentRegion{
  185. id <QNUploadRegion> region = nil;
  186. @synchronized (self) {
  187. if (self.currentRegionIndex < self.regions.count) {
  188. region = self.regions[self.currentRegionIndex];
  189. }
  190. }
  191. return region;
  192. }
  193. - (void)addRegionRequestMetricsOfOneFlow:(QNUploadRegionRequestMetrics *)metrics{
  194. if (metrics == nil) {
  195. return;
  196. }
  197. @synchronized (self) {
  198. if (self.currentRegionRequestMetrics == nil) {
  199. self.currentRegionRequestMetrics = metrics;
  200. return;
  201. }
  202. }
  203. [self.currentRegionRequestMetrics addMetrics:metrics];
  204. }
  205. @end