QNPartsUploadPerformerV1.m 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // QNPartsUploadApiV1.m
  3. // QiniuSDK
  4. //
  5. // Created by yangsen on 2020/11/30.
  6. // Copyright © 2020 Qiniu. All rights reserved.
  7. //
  8. #import "QNLogUtil.h"
  9. #import "QNDefine.h"
  10. #import "QNRequestTransaction.h"
  11. #import "QNUploadFileInfoPartV1.h"
  12. #import "QNPartsUploadPerformerV1.h"
  13. @interface QNPartsUploadPerformerV1()
  14. @end
  15. @implementation QNPartsUploadPerformerV1
  16. + (long long)blockSize{
  17. return 4 * 1024 * 1024;
  18. }
  19. - (QNUploadFileInfo *)getFileInfoWithDictionary:(NSDictionary *)fileInfoDictionary {
  20. return [QNUploadFileInfoPartV1 infoFromDictionary:fileInfoDictionary];
  21. }
  22. - (QNUploadFileInfo *)getDefaultUploadFileInfo {
  23. return [[QNUploadFileInfoPartV1 alloc] initWithFileSize:[self.file size]
  24. blockSize:[QNPartsUploadPerformerV1 blockSize]
  25. dataSize:[self getUploadChunkSize]
  26. modifyTime:[self.file modifyTime]];
  27. }
  28. - (void)serverInit:(void(^)(QNResponseInfo * _Nullable responseInfo,
  29. QNUploadRegionRequestMetrics * _Nullable metrics,
  30. NSDictionary * _Nullable response))completeHandler {
  31. QNResponseInfo *responseInfo = [QNResponseInfo successResponse];
  32. completeHandler(responseInfo, nil, nil);
  33. }
  34. - (void)uploadNextData:(void(^)(BOOL stop,
  35. QNResponseInfo * _Nullable responseInfo,
  36. QNUploadRegionRequestMetrics * _Nullable metrics,
  37. NSDictionary * _Nullable response))completeHandler {
  38. QNUploadFileInfoPartV1 *fileInfo = (QNUploadFileInfoPartV1 *)self.fileInfo;
  39. QNUploadBlock *block = nil;
  40. QNUploadData *chunk = nil;
  41. @synchronized (self) {
  42. block = [fileInfo nextUploadBlock];
  43. chunk = [block nextUploadData];
  44. chunk.isUploading = YES;
  45. chunk.isCompleted = NO;
  46. }
  47. if (block == nil || chunk == nil) {
  48. QNLogInfo(@"key:%@ no chunk left", self.key);
  49. QNResponseInfo *responseInfo = [QNResponseInfo responseInfoWithSDKInteriorError:@"no chunk left"];
  50. completeHandler(YES, responseInfo, nil, nil);
  51. return;
  52. }
  53. NSData *chunkData = [self getDataWithChunk:chunk block:block];
  54. if (chunkData == nil) {
  55. QNLogInfo(@"key:%@ get chunk data error", self.key);
  56. chunk.isUploading = NO;
  57. chunk.isCompleted = NO;
  58. QNResponseInfo *responseInfo = [QNResponseInfo responseInfoWithLocalIOError:@"get chunk data error"];
  59. completeHandler(YES, responseInfo, nil, nil);
  60. return;
  61. }
  62. kQNWeakSelf;
  63. void (^progress)(long long, long long) = ^(long long totalBytesWritten, long long totalBytesExpectedToWrite){
  64. kQNStrongSelf;
  65. chunk.progress = (float)totalBytesWritten / (float)totalBytesExpectedToWrite;
  66. [self notifyProgress];
  67. };
  68. void (^completeHandlerP)(QNResponseInfo *, QNUploadRegionRequestMetrics *, NSDictionary *) = ^(QNResponseInfo * _Nullable responseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, NSDictionary * _Nullable response) {
  69. kQNStrongSelf;
  70. NSString *blockContext = response[@"ctx"];
  71. if (responseInfo.isOK && blockContext) {
  72. block.context = blockContext;
  73. chunk.progress = 1;
  74. chunk.isUploading = NO;
  75. chunk.isCompleted = YES;
  76. [self recordUploadInfo];
  77. [self notifyProgress];
  78. } else {
  79. chunk.isUploading = NO;
  80. chunk.isCompleted = NO;
  81. }
  82. completeHandler(NO, responseInfo, metrics, response);
  83. };
  84. if (chunk.isFirstData) {
  85. QNLogInfo(@"key:%@ makeBlock", self.key);
  86. [self makeBlock:block firstChunk:chunk chunkData:chunkData progress:progress completeHandler:completeHandlerP];
  87. } else {
  88. QNLogInfo(@"key:%@ uploadChunk", self.key);
  89. [self uploadChunk:block chunk:chunk chunkData:chunkData progress:progress completeHandler:completeHandlerP];
  90. }
  91. }
  92. - (void)completeUpload:(void(^)(QNResponseInfo * _Nullable responseInfo,
  93. QNUploadRegionRequestMetrics * _Nullable metrics,
  94. NSDictionary * _Nullable response))completeHandler {
  95. QNUploadFileInfoPartV1 *fileInfo = (QNUploadFileInfoPartV1 *)self.fileInfo;
  96. QNRequestTransaction *transaction = [self createUploadRequestTransaction];
  97. kQNWeakSelf;
  98. kQNWeakObj(transaction);
  99. [transaction makeFile:fileInfo.size
  100. fileName:self.fileName
  101. blockContexts:[fileInfo allBlocksContexts]
  102. complete:^(QNResponseInfo * _Nullable responseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, NSDictionary * _Nullable response) {
  103. kQNStrongSelf;
  104. kQNStrongObj(transaction);
  105. completeHandler(responseInfo, metrics, response);
  106. [self destroyUploadRequestTransaction:transaction];
  107. }];
  108. }
  109. - (void)makeBlock:(QNUploadBlock *)block
  110. firstChunk:(QNUploadData *)chunk
  111. chunkData:(NSData *)chunkData
  112. progress:(void(^)(long long totalBytesWritten,
  113. long long totalBytesExpectedToWrite))progress
  114. completeHandler:(void(^)(QNResponseInfo * _Nullable responseInfo,
  115. QNUploadRegionRequestMetrics * _Nullable metrics,
  116. NSDictionary * _Nullable response))completeHandler {
  117. QNRequestTransaction *transaction = [self createUploadRequestTransaction];
  118. kQNWeakSelf;
  119. kQNWeakObj(transaction);
  120. [transaction makeBlock:block.offset
  121. blockSize:block.size
  122. firstChunkData:chunkData
  123. progress:progress
  124. complete:^(QNResponseInfo * _Nullable responseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, NSDictionary * _Nullable response) {
  125. kQNStrongSelf;
  126. kQNStrongObj(transaction);
  127. completeHandler(responseInfo, metrics, response);
  128. [self destroyUploadRequestTransaction:transaction];
  129. }];
  130. }
  131. - (void)uploadChunk:(QNUploadBlock *)block
  132. chunk:(QNUploadData *)chunk
  133. chunkData:(NSData *)chunkData
  134. progress:(void(^)(long long totalBytesWritten,
  135. long long totalBytesExpectedToWrite))progress
  136. completeHandler:(void(^)(QNResponseInfo * _Nullable responseInfo,
  137. QNUploadRegionRequestMetrics * _Nullable metrics,
  138. NSDictionary * _Nullable response))completeHandler {
  139. QNRequestTransaction *transaction = [self createUploadRequestTransaction];
  140. kQNWeakSelf;
  141. kQNWeakObj(transaction);
  142. [transaction uploadChunk:block.context
  143. blockOffset:block.offset
  144. chunkData:chunkData
  145. chunkOffset:chunk.offset
  146. progress:progress
  147. complete:^(QNResponseInfo * _Nullable responseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, NSDictionary * _Nullable response) {
  148. kQNStrongSelf;
  149. kQNStrongObj(transaction);
  150. completeHandler(responseInfo, metrics, response);
  151. [self destroyUploadRequestTransaction:transaction];
  152. }];
  153. }
  154. - (NSData *)getDataWithChunk:(QNUploadData *)chunk block:(QNUploadBlock *)block{
  155. if (!self.file) {
  156. return nil;
  157. }
  158. NSError *error = nil;
  159. NSData *data = [self.file read:(long)(chunk.offset + block.offset)
  160. size:(long)chunk.size
  161. error:&error];
  162. return error ? nil : data;
  163. }
  164. - (long long)getUploadChunkSize{
  165. if (self.config.useConcurrentResumeUpload) {
  166. return [QNPartsUploadPerformerV1 blockSize];
  167. } else {
  168. return self.config.chunkSize;
  169. }
  170. }
  171. @end