QNPartsUploadPerformer.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 "QNFileDelegate.h"
  15. #import "QNUploadRegionInfo.h"
  16. #import "QNRecorderDelegate.h"
  17. #import "QNUploadDomainRegion.h"
  18. #import "QNPartsUploadPerformer.h"
  19. #import "QNRequestTransaction.h"
  20. #define kQNRecordFileInfoKey @"recordFileInfo"
  21. #define kQNRecordZoneInfoKey @"recordZoneInfo"
  22. @interface QNPartsUploadPerformer()
  23. @property (nonatomic, copy) NSString *key;
  24. @property (nonatomic, copy) NSString *fileName;
  25. @property (nonatomic, strong) id <QNFileDelegate> file;
  26. @property (nonatomic, strong) QNUpToken *token;
  27. @property (nonatomic, strong) QNUploadOption *option;
  28. @property (nonatomic, strong) QNConfiguration *config;
  29. @property (nonatomic, strong) id <QNRecorderDelegate> recorder;
  30. @property (nonatomic, copy) NSString *recorderKey;
  31. @property (nonatomic, strong) NSNumber *recoveredFrom;
  32. @property (nonatomic, strong) id <QNUploadRegion> targetRegion;
  33. @property (nonatomic, strong) id <QNUploadRegion> currentRegion;
  34. @property (nonatomic, strong) QNUploadFileInfo *fileInfo;
  35. @property(nonatomic, assign) double previousPercent;
  36. @property(nonatomic, strong)NSMutableArray <QNRequestTransaction *> *uploadTransactions;
  37. @end
  38. @implementation QNPartsUploadPerformer
  39. - (instancetype)initWithFile:(id<QNFileDelegate>)file
  40. fileName:(NSString *)fileName
  41. key:(NSString *)key
  42. token:(QNUpToken *)token
  43. option:(QNUploadOption *)option
  44. configuration:(QNConfiguration *)config
  45. recorderKey:(NSString *)recorderKey {
  46. if (self = [super init]) {
  47. _file = file;
  48. _fileName = fileName;
  49. _key = key;
  50. _token = token;
  51. _option = option;
  52. _config = config;
  53. _recorder = config.recorder;
  54. _recorderKey = recorderKey;
  55. [self initData];
  56. }
  57. return self;
  58. }
  59. - (void)initData {
  60. self.uploadTransactions = [NSMutableArray array];
  61. [self recoverUploadInfoFromRecord];
  62. if (!self.fileInfo) {
  63. self.fileInfo = [self getDefaultUploadFileInfo];
  64. }
  65. }
  66. - (void)switchRegion:(id <QNUploadRegion>)region {
  67. [self.fileInfo clearUploadState];
  68. self.currentRegion = region;
  69. self.recoveredFrom = nil;
  70. if (!self.targetRegion) {
  71. self.targetRegion = region;
  72. }
  73. }
  74. - (void)notifyProgress {
  75. float percent = self.fileInfo.progress;
  76. if (percent > 0.95) {
  77. percent = 0.95;
  78. }
  79. if (percent > self.previousPercent) {
  80. self.previousPercent = percent;
  81. } else {
  82. percent = self.previousPercent;
  83. }
  84. QNAsyncRunInMain(^{
  85. self.option.progressHandler(self.key, percent);
  86. });
  87. }
  88. - (void)recordUploadInfo {
  89. NSString *key = self.recorderKey;
  90. if (self.recorder == nil || key == nil || key.length == 0) {
  91. return;
  92. }
  93. NSDictionary *zoneInfo = [self.currentRegion zoneInfo].detailInfo;
  94. NSDictionary *fileInfo = [self.fileInfo toDictionary];
  95. if (zoneInfo && fileInfo) {
  96. NSDictionary *info = @{kQNRecordZoneInfoKey : zoneInfo,
  97. kQNRecordFileInfoKey : fileInfo};
  98. NSData *data = [NSJSONSerialization dataWithJSONObject:info options:NSJSONWritingPrettyPrinted error:nil];
  99. if (data) {
  100. [self.recorder set:key data:data];
  101. }
  102. }
  103. QNLogInfo(@"key:%@ recorderKey:%@ recordUploadInfo", self.key, self.recorderKey);
  104. }
  105. - (void)removeUploadInfoRecord {
  106. self.recoveredFrom = nil;
  107. [self.fileInfo clearUploadState];
  108. [self.recorder del:self.recorderKey];
  109. QNLogInfo(@"key:%@ recorderKey:%@ removeUploadInfoRecord", self.key, self.recorderKey);
  110. }
  111. - (void)recoverUploadInfoFromRecord {
  112. QNLogInfo(@"key:%@ recorderKey:%@ recorder:%@ recoverUploadInfoFromRecord", self.key, self.recorderKey, self.recorder);
  113. NSString *key = self.recorderKey;
  114. if (self.recorder == nil || key == nil || [key isEqualToString:@""]) {
  115. return;
  116. }
  117. NSData *data = [self.recorder get:key];
  118. if (data == nil) {
  119. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord data:nil", self.key, self.recorderKey);
  120. return;
  121. }
  122. NSError *error = nil;
  123. NSDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
  124. if (error != nil || ![info isKindOfClass:[NSDictionary class]]) {
  125. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord json error", self.key, self.recorderKey);
  126. [self.recorder del:self.key];
  127. return;
  128. }
  129. QNZoneInfo *zoneInfo = [QNZoneInfo zoneInfoFromDictionary:info[kQNRecordZoneInfoKey]];
  130. QNUploadFileInfo *fileInfo = [self getFileInfoWithDictionary:info[kQNRecordFileInfoKey]];
  131. if (zoneInfo && fileInfo && ![fileInfo isEmpty]
  132. && fileInfo.size == self.file.size && fileInfo.modifyTime == self.file.modifyTime) {
  133. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord valid", self.key, self.recorderKey);
  134. self.fileInfo = fileInfo;
  135. QNUploadDomainRegion *region = [[QNUploadDomainRegion alloc] init];
  136. [region setupRegionData:zoneInfo];
  137. self.currentRegion = region;
  138. self.targetRegion = region;
  139. self.recoveredFrom = @(fileInfo.progress * fileInfo.size);
  140. } else {
  141. QNLogInfo(@"key:%@ recorderKey:%@ recoverUploadInfoFromRecord invalid", self.key, self.recorderKey);
  142. [self.recorder del:self.key];
  143. self.currentRegion = nil;
  144. self.targetRegion = nil;
  145. self.recoveredFrom = nil;
  146. }
  147. }
  148. - (QNRequestTransaction *)createUploadRequestTransaction {
  149. QNRequestTransaction *transaction = [[QNRequestTransaction alloc] initWithConfig:self.config
  150. uploadOption:self.option
  151. targetRegion:self.targetRegion
  152. currentRegion:self.currentRegion
  153. key:self.key
  154. token:self.token];
  155. @synchronized (self) {
  156. [self.uploadTransactions addObject:transaction];
  157. }
  158. return transaction;
  159. }
  160. - (void)destroyUploadRequestTransaction:(QNRequestTransaction *)transaction {
  161. if (transaction) {
  162. @synchronized (self) {
  163. [self.uploadTransactions removeObject:transaction];
  164. }
  165. }
  166. }
  167. - (QNUploadFileInfo *)getFileInfoWithDictionary:(NSDictionary *)fileInfoDictionary {
  168. return nil;
  169. }
  170. - (QNUploadFileInfo *)getDefaultUploadFileInfo {
  171. return nil;
  172. }
  173. - (void)serverInit:(void (^)(QNResponseInfo * _Nullable,
  174. QNUploadRegionRequestMetrics * _Nullable,
  175. NSDictionary * _Nullable))completeHandler {}
  176. - (void)uploadNextData:(void (^)(BOOL stop,
  177. QNResponseInfo * _Nullable,
  178. QNUploadRegionRequestMetrics * _Nullable,
  179. NSDictionary * _Nullable))completeHandler {}
  180. - (void)completeUpload:(void (^)(QNResponseInfo * _Nullable,
  181. QNUploadRegionRequestMetrics * _Nullable,
  182. NSDictionary * _Nullable))completeHandler {}
  183. @end