KMCloudOperation.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. //
  2. // KMCloudOperation.m
  3. // PDF Reader
  4. //
  5. // Created by wanjun on 2020/7/14.
  6. // Copyright © 2020 Kdan Mobile. All rights reserved.
  7. //
  8. #import "KMCloudOperation.h"
  9. #import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
  10. #import "GTMSessionFetcher.h"
  11. #import "KMGoogleDriveManager.h"
  12. @interface KMCloudOperation ()
  13. @property (assign, nonatomic, getter = isExecuting) BOOL executing;
  14. @property (assign, nonatomic, getter = isFinished) BOOL finished;
  15. @property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
  16. @property (nonatomic, strong) KMGoogleDriveManager *cloudModel;
  17. @property (nonatomic, assign) BOOL isDownload;
  18. @property (nonatomic, strong) NSURL *localPath;
  19. /* Google Drive */
  20. @property (nonatomic, strong) GTLRServiceTicket *uploadFileTicket;
  21. @property (nonatomic, strong) GTLRServiceTicket *downloadFileTicket;
  22. /* DropBox */
  23. @property (nonatomic, retain) DBUploadTask *uploadTask;
  24. @property (nonatomic, retain) DBDownloadUrlTask *downloadTask;
  25. @property (nonatomic, strong) KMServicesCloudFile *fileData;
  26. @property (nonatomic, copy) CurrentProgressCallBack progressCallBack;
  27. @property (nonatomic, copy) CompletionCallBack callback;
  28. @property (nonatomic,assign) long long downloadSize;
  29. @property (nonatomic,assign) long long downloadTotalSize;
  30. @end
  31. @implementation KMCloudOperation
  32. @synthesize executing = _executing;
  33. @synthesize finished = _finished;
  34. @synthesize cancelled = _cancelled;
  35. - (void)dealloc {}
  36. #pragma mark - init
  37. - (instancetype)initWithLoadCloudPath:(KMServicesCloudFile *)cloudPath
  38. serverType:(KMServerType)serverType
  39. localPath:(NSURL *)localPath
  40. loadState:(KMCloudLoadState)state
  41. currentConvetProgress:(CurrentProgressCallBack)currentProgress
  42. completion:(CompletionCallBack)completion {
  43. self = [super init];
  44. if (self) {
  45. // if (state) {
  46. // if (serverType == KMDropbox) {
  47. // self.fromPath = cloudPath.displayName;
  48. // self.toPath = [localPath path];
  49. // } else if (serverType == KMGoogleDrive) {
  50. // self.fromPath = cloudPath.fileId;
  51. // self.toPath = [localPath path];
  52. // }
  53. // } else {
  54. // if (serverType == KMDropbox) {
  55. // self.fromPath = [localPath path];
  56. // self.toPath = cloudPath.displayName;
  57. // } else if (serverType == KMGoogleDrive) {
  58. // self.fromPath = [localPath path];
  59. // self.toPath = cloudPath.fileId;
  60. // }
  61. // }
  62. self.fromPath = cloudPath;
  63. self.toPath = [localPath path];
  64. self.cloudLoadState = state;
  65. self.filePath = cloudPath.displayName;
  66. _serverType = serverType;
  67. _localPath = localPath;
  68. _isDownload = state;
  69. self.queuePriority = NSOperationQueuePriorityNormal;
  70. if (serverType == KMGoogleDrive) {
  71. _cloudModel = [KMGoogleDriveManager shareInstance];
  72. }
  73. self.fileData = cloudPath;
  74. self.name = self.filePath;
  75. self.executing = NO;
  76. self.finished = NO;
  77. self.progressCallBack = currentProgress;
  78. self.callback = completion;
  79. self.downloadSize = 0;
  80. }
  81. return self;
  82. }
  83. #pragma mark - setter
  84. - (void)setExecuting:(BOOL)executing
  85. {
  86. [self willChangeValueForKey:@"isExecuting"];
  87. _executing = executing;
  88. [self didChangeValueForKey:@"isExecuting"];
  89. }
  90. - (void)setFinished:(BOOL)finished
  91. {
  92. [self willChangeValueForKey:@"isFinished"];
  93. _finished = finished;
  94. [self didChangeValueForKey:@"isFinished"];
  95. }
  96. - (void)setCancelled:(BOOL)cancelled
  97. {
  98. [self willChangeValueForKey:@"isCancelled"];
  99. _cancelled = cancelled;
  100. [self didChangeValueForKey:@"isCancelled"];
  101. }
  102. #pragma mark - overwrite
  103. - (void)start {
  104. if ([self p_checkCancelled]) {
  105. return;
  106. }
  107. if (self.cloudLoadState == KMCloudLoadState_Download) {
  108. dispatch_async(dispatch_get_main_queue(), ^{
  109. self.state = KMCloudDownLoadOperationStateStart;
  110. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  111. });
  112. }
  113. self.executing = YES;
  114. [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
  115. }
  116. - (void)main {
  117. @try {
  118. if ([self p_checkCancelled]) {
  119. return;
  120. }
  121. if (_isDownload) {
  122. [self cloudDownloadDataWithCloudPath:self.fromPath localPath:_localPath];
  123. } else {
  124. [self cloudUploadDataWithCloudPath:self.toPath localPath:_localPath];
  125. }
  126. while (self.executing) {
  127. if ([self p_checkCancelled]) {
  128. return;
  129. }
  130. }
  131. }
  132. @catch (NSException * e) {
  133. NSLog(@"Exception %@", e);
  134. }
  135. }
  136. - (void)cancel
  137. {
  138. [super cancel];
  139. if (_isDownload) {
  140. //取消下载
  141. if (_serverType == KMDropbox) {
  142. [self.downloadTask cancel];
  143. } else if (_serverType == KMGoogleDrive) {
  144. [_downloadFileTicket cancelTicket];
  145. }
  146. } else {
  147. //取消上传
  148. if (_serverType == KMDropbox) {
  149. [self.uploadTask cancel];
  150. } else if (_serverType == KMGoogleDrive) {
  151. [_uploadFileTicket cancelTicket];
  152. }
  153. }
  154. if (self.executing) {
  155. self.executing = NO;
  156. self.finished = YES;
  157. } else {
  158. self.finished = NO;
  159. }
  160. self.cancelled = YES;
  161. if (self.cloudLoadState == KMCloudLoadState_Download) {
  162. self.state = KMCloudDownLoadOperationStateCancel;
  163. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  164. }
  165. }
  166. #pragma mark - private methods
  167. - (void)p_done
  168. {
  169. self.executing = NO;
  170. self.finished = YES;
  171. }
  172. - (BOOL)p_checkCancelled
  173. {
  174. if (self.cancelled) {
  175. self.finished = YES;
  176. return YES;
  177. }
  178. return NO;
  179. }
  180. #pragma mark - updata
  181. //暂时处理成根据上传到指定文件夹FileID的位置,需要添加替换功能,当文件重名时
  182. - (void)cloudUploadDataWithCloudPath:(NSString *)cloudPath localPath:(NSURL *)localPath {
  183. if (_serverType == KMDropbox) {
  184. [self dropboxUploadDataWithCloudPath:_fromPath.displayName localPath:localPath];
  185. } else if (_serverType == KMGoogleDrive) {
  186. [self googleDriveUploadDataWithCloudPath:_fromPath.fileId localPath:localPath];
  187. }
  188. }
  189. //DropBox
  190. - (void)dropboxUploadDataWithCloudPath:(NSString *)cloudPath localPath:(NSURL *)localPath {
  191. NSData *fileData = [[NSData alloc] initWithContentsOfURL:localPath];
  192. NSString * path = [NSString stringWithFormat:@"%@/%@",cloudPath,[[localPath path] lastPathComponent]];
  193. DBFILESWriteMode *mode = [[DBFILESWriteMode alloc] initWithOverwrite];
  194. DBUserClient *client = [DBClientsManager authorizedClient];
  195. // self.uploadTask = [client.filesRoutes uploadData:cloudPath mode:mode autorename:@(YES) clientModified:nil mute:@(NO) inputData:fileData];
  196. // self.uploadTask = [client.filesRoutes uploadData:path mode:mode autorename:@(YES) clientModified:nil mute:@(NO) propertyGroups:nil strictConflict:nil inputData:fileData];
  197. self.uploadTask = [client.filesRoutes uploadData:cloudPath mode:mode autorename:@(YES) clientModified:nil mute:@(NO) propertyGroups:nil strictConflict:nil contentHash:nil inputData:fileData];
  198. [[self.uploadTask setResponseBlock:^(DBFILESFileMetadata *result, DBFILESUploadError *routeError, DBRequestError *networkError) {
  199. if (result) {
  200. KMServicesCloudFile *fileModel = [[KMServicesCloudFile alloc] init];
  201. fileModel.client_modified = result.clientModified;
  202. fileModel.fileModiDate = result.serverModified;
  203. fileModel.fileId = result.id_;
  204. fileModel.fileName = result.name;
  205. fileModel.displayName = result.pathDisplay;
  206. fileModel.path_lower = result.pathLower;
  207. fileModel.rev = result.rev;
  208. fileModel.fileSize = result.size.integerValue;
  209. fileModel.content_hash = result.contentHash;
  210. fileModel.filetype = KMCloudServiceFileType_File;
  211. if (_callback) {
  212. _callback(self.fileData,YES);
  213. }
  214. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:fileModel,@"CloudFile",nil];
  215. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerUploadSuccessfulNotification object:self userInfo:dict];
  216. [self p_done];
  217. } else {
  218. [self cancel];
  219. KMDropboxErrorMetadata *errorModel = [[KMDropboxErrorMetadata alloc] init];
  220. errorModel.routeError = [NSNumber numberWithInteger:routeError.tag];
  221. errorModel.networkError = [NSNumber numberWithInteger:networkError.statusCode.integerValue];
  222. if (self.callback) {
  223. self.callback(self.fileData,NO);
  224. }
  225. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:errorModel,@"UploadError",nil];
  226. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerUploadFailureNotification object:self userInfo:dict];
  227. }
  228. }] setProgressBlock:^(int64_t bytesUploaded, int64_t totalBytesUploaded, int64_t totalBytesExpectedToUploaded) {
  229. CGFloat loadProgress = totalBytesUploaded/(CGFloat)(totalBytesExpectedToUploaded);
  230. if (_progressCallBack) {
  231. _progressCallBack(self.fileData,loadProgress);
  232. }
  233. }];
  234. }
  235. //Goolge Drive
  236. - (void)googleDriveUploadDataWithCloudPath:(NSString *)cloudPath localPath:(NSURL *)localPath {
  237. NSError *fileError;
  238. if (![localPath checkPromisedItemIsReachableAndReturnError:&fileError]) {
  239. return;
  240. }
  241. GTLRDriveService *service = _cloudModel.driveService;
  242. NSString *filename = [localPath lastPathComponent];
  243. NSString *mimeType = [self MIMETypeFileName:filename defaultMIMEType:@"binary/octet-stream"];
  244. NSData *fileData = [NSData dataWithContentsOfURL:localPath];
  245. GTLRUploadParameters *uploadParameters = [GTLRUploadParameters uploadParametersWithData:fileData
  246. MIMEType:mimeType];
  247. GTLRDrive_File *metadata = [GTLRDrive_File object];
  248. metadata.name = localPath.lastPathComponent;
  249. // if ([cloudPath lengthOfBytesUsingEncoding:NSASCIIStringEncoding] > 0) {
  250. // metadata.parents = @[cloudPath];
  251. // }
  252. if (self.fromPath.parensID) {
  253. metadata.parents = @[self.fromPath.parensID];
  254. }
  255. GTLRDriveQuery_FilesCreate *query = [GTLRDriveQuery_FilesCreate queryWithObject:metadata
  256. uploadParameters:uploadParameters];
  257. query.fields = @"id";
  258. query.executionParameters.uploadProgressBlock = ^(GTLRServiceTicket *callbackTicket,
  259. unsigned long long numberOfBytesRead,
  260. unsigned long long dataLength) {
  261. CGFloat loadProgress = numberOfBytesRead/(CGFloat)(dataLength);
  262. if (_progressCallBack) {
  263. _progressCallBack(self.fileData,loadProgress);
  264. }
  265. };
  266. self.uploadFileTicket = [service executeQuery:query completionHandler:^(GTLRServiceTicket *ticket,
  267. GTLRDrive_File *uploadedFile,
  268. NSError *callbackError) {
  269. self.uploadFileTicket = nil;
  270. if (callbackError == nil) {
  271. // Succeeded
  272. KMServicesCloudFile *fileModel = [[KMServicesCloudFile alloc] init];
  273. fileModel.mimeType = uploadedFile.mimeType;
  274. fileModel.fileId = uploadedFile.identifier;
  275. fileModel.kind = uploadedFile.kind;
  276. fileModel.fileName = uploadedFile.name;
  277. fileModel.ownedByMe = uploadedFile.ownedByMe;
  278. fileModel.fileSize = uploadedFile.size.integerValue;
  279. fileModel.fileModiDate = uploadedFile.modifiedByMeTime.date;
  280. fileModel.lastUserName = uploadedFile.lastModifyingUser.displayName;
  281. fileModel.createdTime = uploadedFile.createdTime.date;
  282. fileModel.parensID = uploadedFile.parents[0];
  283. if (_callback) {
  284. _callback(self.fileData,YES);
  285. }
  286. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:self.fileData,@"CloudFile",nil];
  287. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerUploadSuccessfulNotification object:self userInfo:dict];
  288. [self p_done];
  289. } else {
  290. NSLog(@"Upload Failed callbackError==%@",callbackError);
  291. [self cancel];
  292. if (self.callback) {
  293. self.callback(self.fileData,NO);
  294. }
  295. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  296. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:callbackError,@"UploadError",nil];
  297. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerUploadFailureNotification object:self userInfo:dict];
  298. }
  299. }];
  300. }
  301. - (NSString *)MIMETypeFileName:(NSString *)path
  302. defaultMIMEType:(NSString *)defaultType {
  303. NSString *result = defaultType;
  304. NSString *extension = [path pathExtension];
  305. CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
  306. (__bridge CFStringRef)extension, NULL);
  307. if (uti) {
  308. CFStringRef cfMIMEType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
  309. if (cfMIMEType) {
  310. result = CFBridgingRelease(cfMIMEType);
  311. }
  312. CFRelease(uti);
  313. }
  314. return result;
  315. }
  316. #pragma mark - downdata
  317. - (void)cloudDownloadDataWithCloudPath:(KMServicesCloudFile *)cloudPath localPath:(NSURL *)localPath {
  318. if (_serverType == KMDropbox) {
  319. [self dropboxDownloadDataWithCloudPath:cloudPath localPath:localPath];
  320. } else if (_serverType == KMGoogleDrive) {
  321. [self googleDriveDownloadDataWithCloudPath:cloudPath localPath:localPath];
  322. }
  323. }
  324. //DropBox
  325. - (void)dropboxDownloadDataWithCloudPath:(KMServicesCloudFile *)cloudPath localPath:(NSURL *)localPath {
  326. NSString *formString = cloudPath.displayName;
  327. NSString *fileType = [formString pathExtension];
  328. //判断文件是文件还是文件夹
  329. if ([fileType isEqualToString:@""]) {
  330. [self dropboxMultipleFilesDownloadWithPath:formString toPath:localPath];
  331. } else {
  332. [self dropboxSingleFileDownloadWithPath:formString toPath:localPath];
  333. }
  334. }
  335. //单个文件下载
  336. - (void)dropboxSingleFileDownloadWithPath:(NSString *)fromPath toPath:(NSURL *)toPath {
  337. DBUserClient *client = [DBClientsManager authorizedClient];
  338. self.downloadTask = [client.filesRoutes downloadUrl:fromPath overwrite:NO destination:toPath];
  339. [[self.downloadTask setResponseBlock:^(DBFILESFileMetadata * _Nullable result, DBFILESDownloadError * _Nullable routeError, DBRequestError * _Nullable networkError, NSURL * _Nonnull destination) {
  340. if (result) {
  341. KMServicesCloudFile *fileModel = [[KMServicesCloudFile alloc] init];
  342. fileModel.client_modified = result.clientModified;
  343. fileModel.fileModiDate = result.serverModified;
  344. fileModel.fileId = result.id_;
  345. fileModel.fileName = result.name;
  346. fileModel.displayName = result.pathDisplay;
  347. fileModel.path_lower = result.pathLower;
  348. fileModel.rev = result.rev;
  349. fileModel.fileSize = result.size.integerValue;
  350. fileModel.content_hash = result.contentHash;
  351. fileModel.filetype = KMCloudServiceFileType_File;
  352. if (_callback) {
  353. _callback(self.fileData,YES);
  354. }
  355. if (self.cloudLoadState == KMCloudLoadState_Download) {
  356. self.state = KMCloudDownLoadOperationStateSuccess;
  357. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:fileModel,@"CloudFile",nil];
  358. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  359. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadSuccessfulNotification object:self userInfo:dict];
  360. }
  361. [self p_done];
  362. } else {
  363. [self cancel];
  364. KMDropboxErrorMetadata *errorModel = [[KMDropboxErrorMetadata alloc] init];
  365. errorModel.routeError = [NSNumber numberWithInteger:routeError.tag];
  366. if (self.callback) {
  367. self.callback(self.fileData,NO);
  368. }
  369. if (self.cloudLoadState == KMCloudLoadState_Download) {
  370. self.state = KMCloudDownLoadOperationStateFail;
  371. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  372. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:errorModel,@"DownloadError",nil];
  373. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadFailureNotification object:self userInfo:dict];
  374. }
  375. }
  376. }] setProgressBlock:^(int64_t bytesDownloaded, int64_t totalBytesDownloaded, int64_t totalBytesExpectedToDownload) {
  377. if (self.cloudLoadState == KMCloudLoadState_Download) {
  378. self.state = KMCloudDownLoadOperationStateProgress;
  379. self.downloadSize = (CGFloat)totalBytesDownloaded;
  380. self.downloadTotalSize = (CGFloat)totalBytesExpectedToDownload;
  381. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  382. }
  383. CGFloat loadProgress = totalBytesDownloaded/(CGFloat)(totalBytesExpectedToDownload);
  384. if (_progressCallBack) {
  385. _progressCallBack(self.fileData,loadProgress);
  386. }
  387. }];
  388. }
  389. //多个文件下载为 Zip
  390. - (void)dropboxMultipleFilesDownloadWithPath:(NSString *)fromPath toPath:(NSURL *)toPath {
  391. DBUserClient *client = [DBClientsManager authorizedClient];
  392. // self.downloadTask = [client.filesRoutes downloadZipUrl:fromPath overwrite:NO destination:toPath];
  393. [[self.downloadTask setResponseBlock:^(DBFILESFileMetadata * _Nullable result, DBFILESDownloadError * _Nullable routeError, DBRequestError * _Nullable networkError, NSURL * _Nonnull destination) {
  394. if (result) {
  395. KMServicesCloudFile *fileModel = [[KMServicesCloudFile alloc] init];
  396. fileModel.client_modified = result.clientModified;
  397. fileModel.fileModiDate = result.serverModified;
  398. fileModel.fileId = result.id_;
  399. fileModel.fileName = result.name;
  400. fileModel.displayName = result.pathDisplay;
  401. fileModel.path_lower = result.pathLower;
  402. fileModel.rev = result.rev;
  403. fileModel.fileSize = result.size.integerValue;
  404. fileModel.content_hash = result.contentHash;
  405. fileModel.filetype = KMCloudServiceFileType_File;
  406. if (_callback) {
  407. _callback(self.fileData,YES);
  408. }
  409. if (self.cloudLoadState == KMCloudLoadState_Download) {
  410. self.state = KMCloudDownLoadOperationStateSuccess;
  411. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:fileModel,@"CloudFile",nil];
  412. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadSuccessfulNotification object:self userInfo:dict];
  413. }
  414. [self p_done];
  415. } else {
  416. [self cancel];
  417. KMDropboxErrorMetadata *errorModel = [[KMDropboxErrorMetadata alloc] init];
  418. errorModel.routeError = [NSNumber numberWithInteger:routeError.tag];
  419. if (self.callback) {
  420. self.callback(self.fileData,NO);
  421. }
  422. if (self.cloudLoadState == KMCloudLoadState_Download) {
  423. self.state = KMCloudDownLoadOperationStateFail;
  424. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  425. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:errorModel,@"UploadError",nil];
  426. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadFailureNotification object:self userInfo:dict];
  427. }
  428. }
  429. }] setProgressBlock:^(int64_t bytesDownloaded, int64_t totalBytesDownloaded, int64_t totalBytesExpectedToDownload) {
  430. if (self.cloudLoadState == KMCloudLoadState_Download) {
  431. self.state = KMCloudDownLoadOperationStateProgress;
  432. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  433. }
  434. CGFloat loadProgress = totalBytesDownloaded/(CGFloat)(totalBytesExpectedToDownload);
  435. if (_progressCallBack) {
  436. _progressCallBack(self.fileData,loadProgress);
  437. }
  438. }];
  439. }
  440. //Google Drive
  441. - (void)googleDriveDownloadDataWithCloudPath:(KMServicesCloudFile *)cloudPath localPath:(NSURL *)localPath {
  442. NSString *fileType = @"";
  443. if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.presentation"]) {
  444. fileType = @"application/vnd.openxmlformats-officedocument.presentationml.presentation";
  445. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.document"]) {
  446. fileType = @"application/vnd.openxmlformats-officedocument.wordprocessingml.document";
  447. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.spreadsheet"]) {
  448. fileType = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  449. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.form"]) {
  450. fileType = @"text/csv";
  451. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.map"]) {
  452. fileType = @"application/vnd.google-apps.script+json";
  453. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.drawing"]) {
  454. fileType = @"image/jpeg";
  455. } else if ([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.site"]) {
  456. fileType = @"text/html";
  457. } else if([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.script"]) {
  458. fileType = @"application/vnd.google-apps.script+json";
  459. } else if([cloudPath.mimeType isEqualToString:@"application/vnd.google-apps.photo"]) {
  460. fileType = @"image/jpeg";
  461. }
  462. NSString *formString = cloudPath.fileId;
  463. GTLRDriveService *service = _cloudModel.driveService;
  464. GTLRQuery *query = [GTLRDriveQuery_FilesExport queryForMediaWithFileId:formString mimeType:fileType];
  465. if ([fileType isEqualToString:@""]) {
  466. query = [GTLRDriveQuery_FilesGet queryForMediaWithFileId:formString];
  467. } else {
  468. query = [GTLRDriveQuery_FilesExport queryForMediaWithFileId:formString mimeType:fileType];
  469. }
  470. //下载进度
  471. self.downloadFileTicket = [service executeQuery:query
  472. completionHandler:^(GTLRServiceTicket *callbackTicket,
  473. GTLRDataObject *object,
  474. NSError *callbackError) {
  475. NSError *errorToReport = callbackError;
  476. NSError *writeError;
  477. self.downloadFileTicket = nil;
  478. if (callbackError == nil) {
  479. NSLog(@"object == %@ toPath==%@",object,[localPath path]);
  480. BOOL didSave = [object.data writeToURL:localPath
  481. options:NSDataWritingAtomic
  482. error:&writeError];
  483. if (!didSave) {
  484. errorToReport = writeError;
  485. }
  486. }
  487. if (errorToReport == nil) {
  488. NSLog(@"Downloaded == %@", [localPath path]);
  489. KMServicesCloudFile *fileModel = [[KMServicesCloudFile alloc] init];
  490. fileModel.fileId = formString;
  491. if (_callback) {
  492. _callback(self.fileData,YES);
  493. }
  494. if (self.cloudLoadState == KMCloudLoadState_Download) {
  495. self.state = KMCloudDownLoadOperationStateSuccess;
  496. NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:self.fileData,@"CloudFile",nil];
  497. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadSuccessfulNotification object:self userInfo:dict];
  498. }
  499. [self p_done];
  500. } else {
  501. NSLog(@"Error Downloading File == %@", errorToReport);
  502. [self cancel];
  503. if (self.cloudLoadState == KMCloudLoadState_Download) {
  504. self.state = KMCloudDownLoadOperationStateFail;
  505. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadStateChangeNotification object:self];
  506. [[NSNotificationCenter defaultCenter] postNotificationName:KMServerCloudFileManagerDownloadFailureNotification object:self userInfo:nil];
  507. }
  508. if (_callback) {
  509. _callback(self.fileData,NO);
  510. }
  511. }
  512. }];
  513. }
  514. @end