QNPartsUploadPerformer.m 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //
  2. // QNPartsUploadPerformer.m
  3. // QiniuSDK
  4. //
  5. // Created by yangsen on 2020/12/1.
  6. // Copyright © 2020 Qiniu. All rights reserved.
  7. //
  8. #import "QNLogUtil.h"
  9. #import "QNAsyncRun.h"
  10. #import "QNUpToken.h"
  11. #import "QNZoneInfo.h"
  12. #import "QNUploadOption.h"
  13. #import "QNConfiguration.h"
  14. #import "QNUploadInfo.h"
  15. #import "QNUploadRegionInfo.h"
  16. #import "QNRecorderDelegate.h"
  17. #import "QNUploadDomainRegion.h"
  18. #import "QNPartsUploadPerformer.h"
  19. #import "QNUpProgress.h"
  20. #import "QNRequestTransaction.h"
  21. #define kQNRecordFileInfoKey @"recordFileInfo"
  22. #define kQNRecordZoneInfoKey @"recordZoneInfo"
  23. @interface QNPartsUploadPerformer()
  24. @property (nonatomic, copy) NSString *key;
  25. @property (nonatomic, copy) NSString *fileName;
  26. @property (nonatomic, strong) id <QNUploadSource> uploadSource;
  27. @property (nonatomic, strong) QNUpToken *token;
  28. @property (nonatomic, strong) QNUploadOption *option;
  29. @property (nonatomic, strong) QNConfiguration *config;
  30. @property (nonatomic, strong) id <QNRecorderDelegate> recorder;
  31. @property (nonatomic, copy) NSString *recorderKey;
  32. @property (nonatomic, strong) NSNumber *recoveredFrom;
  33. @property (nonatomic, strong) id <QNUploadRegion> targetRegion;
  34. @property (nonatomic, strong) id <QNUploadRegion> currentRegion;
  35. @property (nonatomic, strong) QNUploadInfo *uploadInfo;
  36. @property(nonatomic, strong) NSLock *progressLocker;
  37. @property(nonatomic, strong) QNUpProgress *progress;
  38. @property(nonatomic, strong) NSMutableArray <QNRequestTransaction *> *uploadTransactions;
  39. @end
  40. @implementation QNPartsUploadPerformer
  41. - (instancetype)initWithSource:(id<QNUploadSource>)uploadSource
  42. fileName:(NSString *)fileName
  43. key:(NSString *)key
  44. token:(QNUpToken *)token
  45. option:(QNUploadOption *)option
  46. configuration:(QNConfiguration *)config
  47. recorderKey:(NSString *)recorderKey {
  48. if (self = [super init]) {
  49. _uploadSource = uploadSource;
  50. _fileName = fileName;
  51. _key = key;
  52. _token = token;
  53. _option = option;
  54. _config = config;
  55. _recorder = config.recorder;
  56. _recorderKey = recorderKey;
  57. [self initData];
  58. }
  59. return self;
  60. }
  61. - (void)initData {
  62. self.uploadTransactions = [NSMutableArray array];
  63. if (!self.uploadInfo) {
  64. self.uploadInfo = [self getDefaultUploadInfo];
  65. }
  66. [self recoverUploadInfoFromRecord];
  67. }
  68. - (BOOL)couldReloadInfo {
  69. return [self.uploadInfo couldReloadSource];
  70. }
  71. - (BOOL)reloadInfo {
  72. self.recoveredFrom = nil;
  73. [self.uploadInfo clearUploadState];
  74. return [self.uploadInfo reloadSource];
  75. }
  76. - (void)switchRegion:(id <QNUploadRegion>)region {
  77. self.currentRegion = region;
  78. if (!self.targetRegion) {
  79. self.targetRegion = region;
  80. }
  81. }
  82. - (void)notifyProgress:(BOOL)isCompleted {
  83. if (self.uploadInfo == nil) {
  84. return;
  85. }
  86. if (isCompleted) {
  87. [self.progress notifyDone:self.key totalBytes:[self.uploadInfo getSourceSize]];
  88. } else {
  89. [self.progress progress:self.key uploadBytes:[self.uploadInfo uploadSize] totalBytes:[self.uploadInfo getSourceSize]];
  90. }
  91. }
  92. - (void)recordUploadInfo {
  93. NSString *key = self.recorderKey;
  94. if (self.recorder == nil || key == nil || key.length == 0) {
  95. return;
  96. }
  97. @synchronized (self) {
  98. NSDictionary *zoneInfo = [self.currentRegion zoneInfo].detailInfo;
  99. NSDictionary *uploadInfo = [self.uploadInfo toDictionary];
  100. if (zoneInfo && uploadInfo) {
  101. NSDictionary *info = @{kQNRecordZoneInfoKey : zoneInfo,
  102. kQNRecordFileInfoKey : uploadInfo};
  103. NSData *data = [NSJSONSerialization dataWithJSONObject:info options:NSJSONWritingPrettyPrinted error:nil];
  104. if (data) {
  105. [self.recorder set:key data:data];
  106. }
  107. }
  108. }
  109. QNLogInfo(@"key:%@ recorderKey:%@ recordUploadInfo", self.key, self.recorderKey);
  110. }
  111. - (void)removeUploadInfoRecord {
  112. self.recoveredFrom = nil;
  113. [self.uploadInfo clearUploadState];
  114. [self.recorder del:self.recorderKey];
  115. QNLogInfo(@"key:%@ recorderKey:%@ removeUploadInfoRecord", self.key, self.recorderKey);
  116. }
  117. - (void)recoverUploadInfoFromRecord {
  118. QNLogInfo(@"key:%@ recorderKey:%@ recorder:%@ recoverUploadInfoFromRecord", self.key, self.recorderKey, self.recorder);
  119. NSString *key = self.recorderKey;
  120. if (self.recorder == nil || key == nil || [key isEqualToString:@""]) {
  121. return;
  122. }
  123. NSData *data = [self.recorder get:key];
  124. if (data == nil) {
  125. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord data:nil", self.key, self.recorderKey);
  126. return;
  127. }
  128. NSError *error = nil;
  129. NSDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
  130. if (error != nil || ![info isKindOfClass:[NSDictionary class]]) {
  131. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord json error", self.key, self.recorderKey);
  132. [self.recorder del:self.key];
  133. return;
  134. }
  135. QNZoneInfo *zoneInfo = [QNZoneInfo zoneInfoFromDictionary:info[kQNRecordZoneInfoKey]];
  136. QNUploadInfo *recoverUploadInfo = [self getFileInfoWithDictionary:info[kQNRecordFileInfoKey]];
  137. if (zoneInfo && self.uploadInfo && [recoverUploadInfo isValid]
  138. && [self.uploadInfo isSameUploadInfo:recoverUploadInfo]) {
  139. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord valid", self.key, self.recorderKey);
  140. [recoverUploadInfo checkInfoStateAndUpdate];
  141. self.uploadInfo = recoverUploadInfo;
  142. QNUploadDomainRegion *region = [[QNUploadDomainRegion alloc] init];
  143. [region setupRegionData:zoneInfo];
  144. self.currentRegion = region;
  145. self.targetRegion = region;
  146. self.recoveredFrom = @([recoverUploadInfo uploadSize]);
  147. } else {
  148. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord invalid", self.key, self.recorderKey);
  149. [self.recorder del:self.key];
  150. self.currentRegion = nil;
  151. self.targetRegion = nil;
  152. self.recoveredFrom = nil;
  153. }
  154. }
  155. - (QNRequestTransaction *)createUploadRequestTransaction {
  156. QNRequestTransaction *transaction = [[QNRequestTransaction alloc] initWithConfig:self.config
  157. uploadOption:self.option
  158. targetRegion:self.targetRegion
  159. currentRegion:self.currentRegion
  160. key:self.key
  161. token:self.token];
  162. @synchronized (self) {
  163. [self.uploadTransactions addObject:transaction];
  164. }
  165. return transaction;
  166. }
  167. - (void)destroyUploadRequestTransaction:(QNRequestTransaction *)transaction {
  168. if (transaction) {
  169. @synchronized (self) {
  170. [self.uploadTransactions removeObject:transaction];
  171. }
  172. }
  173. }
  174. - (QNUploadInfo *)getFileInfoWithDictionary:(NSDictionary *)fileInfoDictionary {
  175. return nil;
  176. }
  177. - (QNUploadInfo *)getDefaultUploadInfo {
  178. return nil;
  179. }
  180. - (void)serverInit:(void (^)(QNResponseInfo * _Nullable,
  181. QNUploadRegionRequestMetrics * _Nullable,
  182. NSDictionary * _Nullable))completeHandler {}
  183. - (void)uploadNextData:(void (^)(BOOL stop,
  184. QNResponseInfo * _Nullable,
  185. QNUploadRegionRequestMetrics * _Nullable,
  186. NSDictionary * _Nullable))completeHandler {}
  187. - (void)completeUpload:(void (^)(QNResponseInfo * _Nullable,
  188. QNUploadRegionRequestMetrics * _Nullable,
  189. NSDictionary * _Nullable))completeHandler {}
  190. - (QNUpProgress *)progress {
  191. [self.progressLocker lock];
  192. if (_progress == nil) {
  193. _progress = [QNUpProgress progress:self.option.progressHandler byteProgress:self.option.byteProgressHandler];
  194. }
  195. [self.progressLocker unlock];
  196. return _progress;
  197. }
  198. @end