OSSClient.m 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123
  1. //
  2. // OSSClient.m
  3. // oss_ios_sdk
  4. //
  5. // Created by zhouzhuo on 8/16/15.
  6. // Copyright (c) 2015 aliyun.com. All rights reserved.
  7. //
  8. #import "OSSClient.h"
  9. #import "OSSDefine.h"
  10. #import "OSSModel.h"
  11. #import "OSSUtil.h"
  12. #import "OSSLog.h"
  13. #import "OSSBolts.h"
  14. #import "OSSNetworking.h"
  15. #import "OSSXMLDictionary.h"
  16. #import "OSSReachabilityManager.h"
  17. #import "OSSIPv6Adapter.h"
  18. #import "OSSNetworkingRequestDelegate.h"
  19. #import "OSSAllRequestNeededMessage.h"
  20. #import "OSSURLRequestRetryHandler.h"
  21. #import "OSSHttpResponseParser.h"
  22. #import "OSSGetObjectACLRequest.h"
  23. #import "OSSDeleteMultipleObjectsRequest.h"
  24. #import "OSSGetBucketInfoRequest.h"
  25. #import "OSSPutSymlinkRequest.h"
  26. #import "OSSGetSymlinkRequest.h"
  27. #import "OSSRestoreObjectRequest.h"
  28. static NSString * const kClientRecordNameWithCommonPrefix = @"oss_partInfos_storage_name";
  29. static NSString * const kClientRecordNameWithCRC64Suffix = @"-crc64";
  30. static NSString * const kClientRecordNameWithSequentialSuffix = @"-sequential";
  31. static NSUInteger const kClientMaximumOfChunks = 5000; //max part number
  32. static NSString * const kClientErrorMessageForEmptyFile = @"the length of file should not be 0!";
  33. static NSString * const kClientErrorMessageForCancelledTask = @"This task has been cancelled!";
  34. /**
  35. * extend OSSRequest to include the ref to networking request object
  36. */
  37. @interface OSSRequest ()
  38. @property (nonatomic, strong) OSSNetworkingRequestDelegate * requestDelegate;
  39. @end
  40. @interface OSSClient()
  41. - (void)enableCRC64WithFlag:(OSSRequestCRCFlag)flag requestDelegate:(OSSNetworkingRequestDelegate *)delegate;
  42. - (OSSTask *)preChecksForRequest:(OSSMultipartUploadRequest *)request;
  43. - (void)checkRequestCrc64Setting:(OSSRequest *)request;
  44. - (OSSTask *)checkNecessaryParamsOfRequest:(OSSMultipartUploadRequest *)request;
  45. - (OSSTask *)checkPartSizeForRequest:(OSSMultipartUploadRequest *)request;
  46. - (NSUInteger)judgePartSizeForMultipartRequest:(OSSMultipartUploadRequest *)request fileSize:(unsigned long long)fileSize;
  47. - (unsigned long long)getSizeWithFilePath:(nonnull NSString *)filePath error:(NSError **)error;
  48. - (NSString *)readUploadIdForRequest:(OSSResumableUploadRequest *)request recordFilePath:(NSString **)recordFilePath sequential:(BOOL)sequential;
  49. - (NSMutableDictionary *)localPartInfosDictoryWithUploadId:(NSString *)uploadId;
  50. - (OSSTask *)persistencePartInfos:(NSDictionary *)partInfos withUploadId:(NSString *)uploadId;
  51. - (OSSTask *)checkFileSizeWithRequest:(OSSMultipartUploadRequest *)request;
  52. + (NSError *)cancelError;
  53. @end
  54. @implementation OSSClient
  55. static NSObject *lock;
  56. - (instancetype)initWithEndpoint:(NSString *)endpoint credentialProvider:(id<OSSCredentialProvider>)credentialProvider {
  57. return [self initWithEndpoint:endpoint credentialProvider:credentialProvider clientConfiguration:[OSSClientConfiguration new]];
  58. }
  59. - (instancetype)initWithEndpoint:(NSString *)endpoint
  60. credentialProvider:(id<OSSCredentialProvider>)credentialProvider
  61. clientConfiguration:(OSSClientConfiguration *)conf {
  62. if (self = [super init]) {
  63. if (!lock) {
  64. lock = [NSObject new];
  65. }
  66. // Monitor the network. If the network type is changed, recheck the IPv6 status.
  67. [OSSReachabilityManager shareInstance];
  68. NSOperationQueue * queue = [NSOperationQueue new];
  69. // using for resumable upload and compat old interface
  70. queue.maxConcurrentOperationCount = 3;
  71. _ossOperationExecutor = [OSSExecutor executorWithOperationQueue:queue];
  72. if (![endpoint oss_isNotEmpty]) {
  73. [NSException raise:NSInvalidArgumentException
  74. format:@"endpoint should not be nil or empty!"];
  75. }
  76. if ([endpoint rangeOfString:@"://"].location == NSNotFound) {
  77. endpoint = [@"https://" stringByAppendingString:endpoint];
  78. }
  79. NSURL *endpointURL = [NSURL URLWithString:endpoint];
  80. if ([endpointURL.scheme.lowercaseString isEqualToString:@"https"]) {
  81. if ([[OSSIPv6Adapter getInstance] isIPv4Address: endpointURL.host] || [[OSSIPv6Adapter getInstance] isIPv6Address: endpointURL.host]) {
  82. [NSException raise:NSInvalidArgumentException
  83. format:@"unsupported format of endpoint, please use right endpoint format!"];
  84. }
  85. }
  86. self.endpoint = [endpoint oss_trim];
  87. self.credentialProvider = credentialProvider;
  88. self.clientConfiguration = conf;
  89. OSSNetworkingConfiguration * netConf = [OSSNetworkingConfiguration new];
  90. if (conf) {
  91. netConf.maxRetryCount = conf.maxRetryCount;
  92. netConf.timeoutIntervalForRequest = conf.timeoutIntervalForRequest;
  93. netConf.timeoutIntervalForResource = conf.timeoutIntervalForResource;
  94. netConf.enableBackgroundTransmitService = conf.enableBackgroundTransmitService;
  95. netConf.backgroundSessionIdentifier = conf.backgroundSesseionIdentifier;
  96. netConf.proxyHost = conf.proxyHost;
  97. netConf.proxyPort = conf.proxyPort;
  98. netConf.maxConcurrentRequestCount = conf.maxConcurrentRequestCount;
  99. }
  100. self.networking = [[OSSNetworking alloc] initWithConfiguration:netConf];
  101. }
  102. return self;
  103. }
  104. - (OSSTask *)invokeRequest:(OSSNetworkingRequestDelegate *)request requireAuthentication:(BOOL)requireAuthentication {
  105. /* if content-type haven't been set, we set one */
  106. if (!request.allNeededMessage.contentType.oss_isNotEmpty
  107. && ([request.allNeededMessage.httpMethod isEqualToString:@"POST"] || [request.allNeededMessage.httpMethod isEqualToString:@"PUT"])) {
  108. request.allNeededMessage.contentType = [OSSUtil detemineMimeTypeForFilePath:request.uploadingFileURL.path uploadName:request.allNeededMessage.objectKey];
  109. }
  110. // Checks if the endpoint is in the excluded CName list.
  111. [self.clientConfiguration.cnameExcludeList enumerateObjectsUsingBlock:^(NSString *exclude, NSUInteger idx, BOOL * _Nonnull stop) {
  112. if ([self.endpoint hasSuffix:exclude]) {
  113. request.allNeededMessage.isHostInCnameExcludeList = YES;
  114. *stop = YES;
  115. }
  116. }];
  117. id<OSSRequestInterceptor> uaSetting = [[OSSUASettingInterceptor alloc] initWithClientConfiguration:self.clientConfiguration];
  118. [request.interceptors addObject:uaSetting];
  119. /* check if the authentication is required */
  120. if (requireAuthentication) {
  121. id<OSSRequestInterceptor> signer = [[OSSSignerInterceptor alloc] initWithCredentialProvider:self.credentialProvider];
  122. [request.interceptors addObject:signer];
  123. }
  124. request.isHttpdnsEnable = self.clientConfiguration.isHttpdnsEnable;
  125. request.isPathStyleAccessEnable = self.clientConfiguration.isPathStyleAccessEnable;
  126. request.isCustomPathPrefixEnable = self.clientConfiguration.isCustomPathPrefixEnable;
  127. return [_networking sendRequest:request];
  128. }
  129. #pragma implement restful apis
  130. - (OSSTask *)getService:(OSSGetServiceRequest *)request {
  131. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  132. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetService];
  133. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  134. neededMsg.endpoint = self.endpoint;
  135. neededMsg.httpMethod = OSSHTTPMethodGET;
  136. neededMsg.params = [request requestParams];
  137. requestDelegate.allNeededMessage = neededMsg;
  138. requestDelegate.operType = OSSOperationTypeGetService;
  139. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  140. }
  141. # pragma mark - Private Methods
  142. - (void)enableCRC64WithFlag:(OSSRequestCRCFlag)flag requestDelegate:(OSSNetworkingRequestDelegate *)delegate
  143. {
  144. switch (flag) {
  145. case OSSRequestCRCOpen:
  146. delegate.crc64Verifiable = YES;
  147. break;
  148. case OSSRequestCRCClosed:
  149. delegate.crc64Verifiable = NO;
  150. break;
  151. default:
  152. delegate.crc64Verifiable = self.clientConfiguration.crc64Verifiable;
  153. break;
  154. }
  155. }
  156. - (OSSTask *)preChecksForRequest:(OSSMultipartUploadRequest *)request
  157. {
  158. OSSTask *preTask = [self checkFileSizeWithRequest:request];
  159. if (preTask) {
  160. return preTask;
  161. }
  162. preTask = [self checkNecessaryParamsOfRequest:request];
  163. if (preTask) {
  164. return preTask;
  165. }
  166. preTask = [self checkPartSizeForRequest:request];
  167. if (preTask) {
  168. return preTask;
  169. }
  170. return preTask;
  171. }
  172. - (void)checkRequestCrc64Setting:(OSSRequest *)request
  173. {
  174. if (request.crcFlag == OSSRequestCRCUninitialized)
  175. {
  176. if (self.clientConfiguration.crc64Verifiable)
  177. {
  178. request.crcFlag = OSSRequestCRCOpen;
  179. }else
  180. {
  181. request.crcFlag = OSSRequestCRCClosed;
  182. }
  183. }
  184. }
  185. - (OSSTask *)checkNecessaryParamsOfRequest:(OSSMultipartUploadRequest *)request
  186. {
  187. NSError *error = nil;
  188. if (![request.objectKey oss_isNotEmpty]) {
  189. error = [NSError errorWithDomain:OSSClientErrorDomain
  190. code:OSSClientErrorCodeInvalidArgument
  191. userInfo:@{OSSErrorMessageTOKEN: @"checkNecessaryParamsOfRequest requires nonnull objectKey!"}];
  192. }else if (![request.bucketName oss_isNotEmpty]) {
  193. error = [NSError errorWithDomain:OSSClientErrorDomain
  194. code:OSSClientErrorCodeInvalidArgument
  195. userInfo:@{OSSErrorMessageTOKEN: @"checkNecessaryParamsOfRequest requires nonnull bucketName!"}];
  196. }else if (![request.uploadingFileURL.path oss_isNotEmpty]) {
  197. error = [NSError errorWithDomain:OSSClientErrorDomain
  198. code:OSSClientErrorCodeInvalidArgument
  199. userInfo:@{OSSErrorMessageTOKEN: @"checkNecessaryParamsOfRequest requires nonnull uploadingFileURL!"}];
  200. }
  201. OSSTask *errorTask = nil;
  202. if (error) {
  203. errorTask = [OSSTask taskWithError:error];
  204. }
  205. return errorTask;
  206. }
  207. - (OSSTask *)checkPartSizeForRequest:(OSSMultipartUploadRequest *)request
  208. {
  209. OSSTask *errorTask = nil;
  210. unsigned long long fileSize = [self getSizeWithFilePath:request.uploadingFileURL.path error:nil];
  211. if (request.partSize == 0 || (fileSize > 102400 && request.partSize < 102400)) {
  212. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  213. code:OSSClientErrorCodeInvalidArgument
  214. userInfo:@{OSSErrorMessageTOKEN: @"Part size must be greater than equal to 100KB"}];
  215. errorTask = [OSSTask taskWithError:error];
  216. }
  217. return errorTask;
  218. }
  219. - (NSUInteger)judgePartSizeForMultipartRequest:(OSSMultipartUploadRequest *)request fileSize:(unsigned long long)fileSize
  220. {
  221. #pragma clang diagnostic push
  222. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  223. BOOL divisible = (fileSize % request.partSize == 0);
  224. NSUInteger partCount = (fileSize / request.partSize) + (divisible? 0 : 1);
  225. if(partCount > kClientMaximumOfChunks)
  226. {
  227. request.partSize = fileSize / kClientMaximumOfChunks;
  228. partCount = kClientMaximumOfChunks;
  229. }
  230. return partCount;
  231. #pragma clang diagnostic pop
  232. }
  233. - (unsigned long long)getSizeWithFilePath:(nonnull NSString *)filePath error:(NSError **)error
  234. {
  235. NSFileManager *fm = [NSFileManager defaultManager];
  236. NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:error];
  237. return attributes.fileSize;
  238. }
  239. - (NSString *)readUploadIdForRequest:(OSSResumableUploadRequest *)request recordFilePath:(NSString **)recordFilePath sequential:(BOOL)sequential
  240. {
  241. NSString *uploadId = nil;
  242. NSString *record = [NSString stringWithFormat:@"%@%@%@%lu", request.md5String, request.bucketName, request.objectKey, (unsigned long)request.partSize];
  243. if (sequential) {
  244. record = [record stringByAppendingString:kClientRecordNameWithSequentialSuffix];
  245. }
  246. if (request.crcFlag == OSSRequestCRCOpen) {
  247. record = [record stringByAppendingString:kClientRecordNameWithCRC64Suffix];
  248. }
  249. NSData *data = [record dataUsingEncoding:NSUTF8StringEncoding];
  250. NSString *recordFileName = [OSSUtil dataMD5String:data];
  251. *recordFilePath = [request.recordDirectoryPath stringByAppendingPathComponent: recordFileName];
  252. NSFileManager *fileManager = [NSFileManager defaultManager];
  253. if ([fileManager fileExistsAtPath: *recordFilePath]) {
  254. NSFileHandle * read = [NSFileHandle fileHandleForReadingAtPath:*recordFilePath];
  255. uploadId = [[NSString alloc] initWithData:[read readDataToEndOfFile] encoding:NSUTF8StringEncoding];
  256. [read closeFile];
  257. } else {
  258. [fileManager createFileAtPath:*recordFilePath contents:nil attributes:nil];
  259. }
  260. return uploadId;
  261. }
  262. #pragma mark - sequential multipart upload
  263. - (NSMutableDictionary *)localPartInfosDictoryWithUploadId:(NSString *)uploadId
  264. {
  265. NSMutableDictionary *localPartInfoDict = nil;
  266. NSString *partInfosDirectory = [[NSString oss_documentDirectory] stringByAppendingPathComponent:kClientRecordNameWithCommonPrefix];
  267. NSString *partInfosPath = [partInfosDirectory stringByAppendingPathComponent:uploadId];
  268. BOOL isDirectory;
  269. NSFileManager *defaultFM = [NSFileManager defaultManager];
  270. if (!([defaultFM fileExistsAtPath:partInfosDirectory isDirectory:&isDirectory] && isDirectory))
  271. {
  272. if (![defaultFM createDirectoryAtPath:partInfosDirectory
  273. withIntermediateDirectories:NO
  274. attributes:nil error:nil]) {
  275. OSSLogError(@"create Directory(%@) failed!",partInfosDirectory);
  276. };
  277. }
  278. if (![defaultFM fileExistsAtPath:partInfosPath])
  279. {
  280. if (![defaultFM createFileAtPath:partInfosPath
  281. contents:nil
  282. attributes:nil])
  283. {
  284. OSSLogError(@"create local partInfo file failed!");
  285. }
  286. }
  287. localPartInfoDict = [[NSMutableDictionary alloc] initWithContentsOfURL:[NSURL fileURLWithPath:partInfosPath]];
  288. return localPartInfoDict;
  289. }
  290. - (OSSTask *)persistencePartInfos:(NSDictionary *)partInfos withUploadId:(NSString *)uploadId
  291. {
  292. NSString *filePath = [[[NSString oss_documentDirectory] stringByAppendingPathComponent:kClientRecordNameWithCommonPrefix] stringByAppendingPathComponent:uploadId];
  293. if (![partInfos writeToFile:filePath atomically:YES])
  294. {
  295. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  296. code:OSSClientErrorCodeFileCantWrite
  297. userInfo:@{OSSErrorMessageTOKEN: @"uploadId for this task can't be stored persistentially!"}];
  298. OSSLogDebug(@"[Error]: %@", error);
  299. return [OSSTask taskWithError:error];
  300. }
  301. return nil;
  302. }
  303. - (OSSTask *)checkPutObjectFileURL:(OSSPutObjectRequest *)request {
  304. NSError *error = nil;
  305. if (!request.uploadingFileURL || ![request.uploadingFileURL.path oss_isNotEmpty]) {
  306. error = [NSError errorWithDomain:OSSClientErrorDomain
  307. code:OSSClientErrorCodeInvalidArgument
  308. userInfo:@{OSSErrorMessageTOKEN: @"Please check your request's uploadingFileURL!"}];
  309. } else {
  310. NSFileManager *dfm = [NSFileManager defaultManager];
  311. NSDictionary *attributes = [dfm attributesOfItemAtPath:request.uploadingFileURL.path error:&error];
  312. unsigned long long fileSize = [attributes[NSFileSize] unsignedLongLongValue];
  313. if (!error && fileSize == 0) {
  314. error = [NSError errorWithDomain:OSSClientErrorDomain
  315. code:OSSClientErrorCodeInvalidArgument
  316. userInfo:@{OSSErrorMessageTOKEN: kClientErrorMessageForEmptyFile}];
  317. }
  318. }
  319. if (error) {
  320. return [OSSTask taskWithError:error];
  321. } else {
  322. return [OSSTask taskWithResult:nil];
  323. }
  324. }
  325. - (OSSTask *)checkFileSizeWithRequest:(OSSMultipartUploadRequest *)request {
  326. NSError *error = nil;
  327. if (!request.uploadingFileURL || ![request.uploadingFileURL.path oss_isNotEmpty]) {
  328. error = [NSError errorWithDomain:OSSClientErrorDomain
  329. code:OSSClientErrorCodeInvalidArgument
  330. userInfo:@{OSSErrorMessageTOKEN: @"Please check your request's uploadingFileURL!"}];
  331. }
  332. else
  333. {
  334. NSFileManager *dfm = [NSFileManager defaultManager];
  335. NSDictionary *attributes = [dfm attributesOfItemAtPath:request.uploadingFileURL.path error:&error];
  336. unsigned long long fileSize = [attributes[NSFileSize] unsignedLongLongValue];
  337. if (!error && fileSize == 0) {
  338. error = [NSError errorWithDomain:OSSClientErrorDomain
  339. code:OSSClientErrorCodeInvalidArgument
  340. userInfo:@{OSSErrorMessageTOKEN: kClientErrorMessageForEmptyFile}];
  341. }
  342. }
  343. if (error) {
  344. return [OSSTask taskWithError:error];
  345. } else {
  346. return nil;
  347. }
  348. }
  349. + (NSError *)cancelError{
  350. static NSError *error = nil;
  351. static dispatch_once_t onceToken;
  352. dispatch_once(&onceToken, ^{
  353. error = [NSError errorWithDomain:OSSClientErrorDomain
  354. code:OSSClientErrorCodeTaskCancelled
  355. userInfo:@{OSSErrorMessageTOKEN: kClientErrorMessageForCancelledTask}];
  356. });
  357. return error;
  358. }
  359. - (void)dealloc{
  360. [self.networking.session invalidateAndCancel];
  361. }
  362. @end
  363. @implementation OSSClient (Bucket)
  364. - (OSSTask *)createBucket:(OSSCreateBucketRequest *)request {
  365. OSSNetworkingRequestDelegate *requestDelegate = request.requestDelegate;
  366. NSMutableDictionary *headerParams = [NSMutableDictionary dictionary];
  367. [headerParams oss_setObject:request.xOssACL forKey:OSSHttpHeaderBucketACL];
  368. if (request.location) {
  369. requestDelegate.uploadingData = [OSSUtil constructHttpBodyForCreateBucketWithLocation:request.location];
  370. }
  371. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeCreateBucket];
  372. NSString *bodyString = [NSString stringWithFormat:@"<?xml version='1.0' encoding='UTF-8'?><CreateBucketConfiguration><StorageClass>%@</StorageClass></CreateBucketConfiguration>", request.storageClassAsString];
  373. requestDelegate.uploadingData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
  374. NSString *md5String = [OSSUtil base64Md5ForData:requestDelegate.uploadingData];
  375. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  376. neededMsg.endpoint = self.endpoint;
  377. neededMsg.httpMethod = OSSHTTPMethodPUT;
  378. neededMsg.bucketName = request.bucketName;
  379. neededMsg.headerParams = headerParams;
  380. neededMsg.contentMd5 = md5String;
  381. requestDelegate.allNeededMessage = neededMsg;
  382. requestDelegate.operType = OSSOperationTypeCreateBucket;
  383. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  384. }
  385. - (OSSTask *)deleteBucket:(OSSDeleteObjectRequest *)request {
  386. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  387. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeDeleteBucket];
  388. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  389. neededMsg.endpoint = self.endpoint;
  390. neededMsg.httpMethod = OSSHTTPMethodDELETE;
  391. neededMsg.bucketName = request.bucketName;
  392. requestDelegate.allNeededMessage = neededMsg;
  393. requestDelegate.operType = OSSOperationTypeDeleteBucket;
  394. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  395. }
  396. - (OSSTask *)getBucket:(OSSGetBucketRequest *)request {
  397. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  398. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetBucket];
  399. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  400. neededMsg.endpoint = self.endpoint;
  401. neededMsg.httpMethod = OSSHTTPMethodGET;
  402. neededMsg.bucketName = request.bucketName;
  403. neededMsg.params = request.requestParams;
  404. requestDelegate.allNeededMessage = neededMsg;
  405. requestDelegate.operType = OSSOperationTypeGetBucket;
  406. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  407. }
  408. - (OSSTask *)getBucketInfo:(OSSGetBucketInfoRequest *)request {
  409. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  410. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetBucketInfo];
  411. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  412. neededMsg.endpoint = self.endpoint;
  413. neededMsg.httpMethod = OSSHTTPMethodGET;
  414. neededMsg.bucketName = request.bucketName;
  415. neededMsg.params = request.requestParams;
  416. requestDelegate.allNeededMessage = neededMsg;
  417. requestDelegate.operType = OSSOperationTypeGetBucketInfo;
  418. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  419. }
  420. - (OSSTask *)getBucketACL:(OSSGetBucketACLRequest *)request {
  421. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  422. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetBucketACL];
  423. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  424. neededMsg.endpoint = self.endpoint;
  425. neededMsg.httpMethod = OSSHTTPMethodGET;
  426. neededMsg.bucketName = request.bucketName;
  427. neededMsg.params = request.requestParams;
  428. requestDelegate.allNeededMessage = neededMsg;
  429. requestDelegate.operType = OSSOperationTypeGetBucketACL;
  430. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  431. }
  432. @end
  433. @implementation OSSClient (Object)
  434. - (OSSTask *)headObject:(OSSHeadObjectRequest *)request {
  435. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  436. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeHeadObject];
  437. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  438. neededMsg.endpoint = self.endpoint;
  439. neededMsg.httpMethod = OSSHTTPMethodHEAD;
  440. neededMsg.bucketName = request.bucketName;
  441. neededMsg.objectKey = request.objectKey;
  442. requestDelegate.allNeededMessage = neededMsg;
  443. requestDelegate.operType = OSSOperationTypeHeadObject;
  444. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  445. }
  446. - (OSSTask *)getObject:(OSSGetObjectRequest *)request {
  447. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  448. NSString * rangeString = nil;
  449. if (request.range) {
  450. rangeString = [request.range toHeaderString];
  451. }
  452. if (request.downloadProgress) {
  453. requestDelegate.downloadProgress = request.downloadProgress;
  454. }
  455. if (request.onRecieveData) {
  456. requestDelegate.onRecieveData = request.onRecieveData;
  457. }
  458. NSMutableDictionary * params = [NSMutableDictionary dictionary];
  459. [params oss_setObject:request.xOssProcess forKey:OSSHttpQueryProcess];
  460. [self enableCRC64WithFlag:request.crcFlag requestDelegate:requestDelegate];
  461. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetObject];
  462. responseParser.crc64Verifiable = requestDelegate.crc64Verifiable;
  463. requestDelegate.responseParser = responseParser;
  464. requestDelegate.responseParser.downloadingFileURL = request.downloadToFileURL;
  465. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  466. neededMsg.endpoint = self.endpoint;
  467. neededMsg.httpMethod = OSSHTTPMethodGET;
  468. neededMsg.bucketName = request.bucketName;
  469. neededMsg.objectKey = request.objectKey;
  470. neededMsg.range = rangeString;
  471. neededMsg.params = params;
  472. neededMsg.headerParams = request.headerFields;
  473. requestDelegate.allNeededMessage = neededMsg;
  474. requestDelegate.operType = OSSOperationTypeGetObject;
  475. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  476. }
  477. - (OSSTask *)getObjectACL:(OSSGetObjectACLRequest *)request
  478. {
  479. OSSNetworkingRequestDelegate *requestDelegate = request.requestDelegate;
  480. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetObjectACL];
  481. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  482. [params oss_setObject:@"" forKey:@"acl"];
  483. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  484. neededMsg.endpoint = self.endpoint;
  485. neededMsg.httpMethod = OSSHTTPMethodGET;
  486. neededMsg.bucketName = request.bucketName;
  487. neededMsg.objectKey = request.objectName;
  488. neededMsg.params = params;
  489. requestDelegate.allNeededMessage = neededMsg;
  490. requestDelegate.operType = OSSOperationTypeGetObjectACL;
  491. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  492. }
  493. - (OSSTask *)putObject:(OSSPutObjectRequest *)request
  494. {
  495. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  496. NSMutableDictionary * headerParams = [NSMutableDictionary dictionaryWithDictionary:request.objectMeta];
  497. [self enableCRC64WithFlag:request.crcFlag requestDelegate:requestDelegate];
  498. if (request.uploadingData) {
  499. requestDelegate.uploadingData = request.uploadingData;
  500. if (requestDelegate.crc64Verifiable)
  501. {
  502. NSMutableData *mutableData = [NSMutableData dataWithData:request.uploadingData];
  503. requestDelegate.contentCRC = [NSString stringWithFormat:@"%llu",[mutableData oss_crc64]];
  504. }
  505. }
  506. if (request.uploadingFileURL) {
  507. OSSTask *checkIfEmptyTask = [self checkPutObjectFileURL:request];
  508. if (checkIfEmptyTask.error) {
  509. return checkIfEmptyTask;
  510. }
  511. requestDelegate.uploadingFileURL = request.uploadingFileURL;
  512. }
  513. if (request.uploadProgress) {
  514. requestDelegate.uploadProgress = request.uploadProgress;
  515. }
  516. if (request.uploadRetryCallback) {
  517. requestDelegate.retryCallback = request.uploadRetryCallback;
  518. }
  519. [headerParams oss_setObject:[request.callbackParam base64JsonString] forKey:OSSHttpHeaderXOSSCallback];
  520. [headerParams oss_setObject:[request.callbackVar base64JsonString] forKey:OSSHttpHeaderXOSSCallbackVar];
  521. [headerParams oss_setObject:request.contentDisposition forKey:OSSHttpHeaderContentDisposition];
  522. [headerParams oss_setObject:request.contentEncoding forKey:OSSHttpHeaderContentEncoding];
  523. [headerParams oss_setObject:request.expires forKey:OSSHttpHeaderExpires];
  524. [headerParams oss_setObject:request.cacheControl forKey:OSSHttpHeaderCacheControl];
  525. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypePutObject];
  526. responseParser.crc64Verifiable = requestDelegate.crc64Verifiable;
  527. requestDelegate.responseParser = responseParser;
  528. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  529. neededMsg.endpoint = self.endpoint;
  530. neededMsg.httpMethod = OSSHTTPMethodPUT;
  531. neededMsg.bucketName = request.bucketName;
  532. neededMsg.objectKey = request.objectKey;
  533. neededMsg.contentMd5 = request.contentMd5;
  534. neededMsg.contentType = request.contentType;
  535. neededMsg.headerParams = headerParams;
  536. neededMsg.contentSHA1 = request.contentSHA1;
  537. requestDelegate.allNeededMessage = neededMsg;
  538. requestDelegate.operType = OSSOperationTypePutObject;
  539. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  540. }
  541. - (OSSTask *)putObjectACL:(OSSPutObjectACLRequest *)request {
  542. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  543. if (request.uploadRetryCallback) {
  544. requestDelegate.retryCallback = request.uploadRetryCallback;
  545. }
  546. NSMutableDictionary * headerParams = [NSMutableDictionary dictionary];
  547. [headerParams oss_setObject:request.acl forKey:OSSHttpHeaderObjectACL];
  548. NSMutableDictionary * params = [NSMutableDictionary dictionary];
  549. [params oss_setObject:@"" forKey:@"acl"];
  550. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypePutObjectACL];
  551. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  552. neededMsg.endpoint = self.endpoint;
  553. neededMsg.httpMethod = OSSHTTPMethodPUT;
  554. neededMsg.bucketName = request.bucketName;
  555. neededMsg.objectKey = request.objectKey;
  556. neededMsg.params = params;
  557. neededMsg.headerParams = headerParams;
  558. requestDelegate.allNeededMessage = neededMsg;
  559. requestDelegate.operType = OSSOperationTypePutObjectACL;
  560. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  561. }
  562. - (OSSTask *)appendObject:(OSSAppendObjectRequest *)request
  563. {
  564. return [self appendObject:request withCrc64ecma:nil];
  565. }
  566. - (OSSTask *)appendObject:(OSSAppendObjectRequest *)request withCrc64ecma:(nullable NSString *)crc64ecma
  567. {
  568. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  569. requestDelegate.lastCRC = crc64ecma;
  570. [self enableCRC64WithFlag:request.crcFlag requestDelegate:requestDelegate];
  571. if (request.uploadingData)
  572. {
  573. requestDelegate.uploadingData = request.uploadingData;
  574. if (requestDelegate.crc64Verifiable)
  575. {
  576. NSMutableData *mutableData = [NSMutableData dataWithData:request.uploadingData];
  577. requestDelegate.contentCRC = [NSString stringWithFormat:@"%llu",[mutableData oss_crc64]];
  578. }
  579. }
  580. if (request.uploadingFileURL) {
  581. requestDelegate.uploadingFileURL = request.uploadingFileURL;
  582. }
  583. if (request.uploadProgress) {
  584. requestDelegate.uploadProgress = request.uploadProgress;
  585. }
  586. NSMutableDictionary * headerParams = [NSMutableDictionary dictionaryWithDictionary:request.objectMeta];
  587. [headerParams oss_setObject:request.contentDisposition forKey:OSSHttpHeaderContentDisposition];
  588. [headerParams oss_setObject:request.contentEncoding forKey:OSSHttpHeaderContentEncoding];
  589. [headerParams oss_setObject:request.expires forKey:OSSHttpHeaderExpires];
  590. [headerParams oss_setObject:request.cacheControl forKey:OSSHttpHeaderCacheControl];
  591. NSMutableDictionary* params = [NSMutableDictionary dictionary];
  592. [params oss_setObject:@"" forKey:@"append"];
  593. [params oss_setObject:[@(request.appendPosition) stringValue] forKey:@"position"];
  594. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeAppendObject];
  595. responseParser.crc64Verifiable = requestDelegate.crc64Verifiable;
  596. requestDelegate.responseParser = responseParser;
  597. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  598. neededMsg.endpoint = self.endpoint;
  599. neededMsg.httpMethod = OSSHTTPMethodPOST;
  600. neededMsg.bucketName = request.bucketName;
  601. neededMsg.objectKey = request.objectKey;
  602. neededMsg.contentType = request.contentType;
  603. neededMsg.contentMd5 = request.contentMd5;
  604. neededMsg.headerParams = headerParams;
  605. neededMsg.params = params;
  606. neededMsg.contentSHA1 = request.contentSHA1;
  607. requestDelegate.allNeededMessage = neededMsg;
  608. requestDelegate.operType = OSSOperationTypeAppendObject;
  609. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  610. }
  611. - (OSSTask *)deleteObject:(OSSDeleteObjectRequest *)request {
  612. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  613. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypePutObject];
  614. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  615. neededMsg.endpoint = self.endpoint;
  616. neededMsg.httpMethod = OSSHTTPMethodDELETE;
  617. neededMsg.bucketName = request.bucketName;
  618. neededMsg.objectKey = request.objectKey;
  619. requestDelegate.allNeededMessage = neededMsg;
  620. requestDelegate.operType = OSSOperationTypeDeleteObject;
  621. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  622. }
  623. - (OSSTask *)deleteMultipleObjects:(OSSDeleteMultipleObjectsRequest *)request
  624. {
  625. if ([request.keys count] == 0) {
  626. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  627. code:OSSClientErrorCodeInvalidArgument
  628. userInfo:@{OSSErrorMessageTOKEN: @"keys should not be empty"}];
  629. return [OSSTask taskWithError:error];
  630. }
  631. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  632. requestDelegate.uploadingData = [OSSUtil constructHttpBodyForDeleteMultipleObjects:request.keys quiet:request.quiet];
  633. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeDeleteMultipleObjects];
  634. NSString *md5String = [OSSUtil base64Md5ForData:requestDelegate.uploadingData];
  635. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  636. [params oss_setObject:@"" forKey:@"delete"];
  637. [params oss_setObject:request.encodingType forKey:@"encoding-type"];
  638. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  639. neededMsg.endpoint = self.endpoint;
  640. neededMsg.httpMethod = OSSHTTPMethodPOST;
  641. neededMsg.bucketName = request.bucketName;
  642. neededMsg.contentMd5 = md5String;
  643. neededMsg.params = params;
  644. requestDelegate.allNeededMessage = neededMsg;
  645. requestDelegate.operType = OSSOperationTypeDeleteMultipleObjects;
  646. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  647. }
  648. - (OSSTask *)copyObject:(OSSCopyObjectRequest *)request {
  649. NSString *copySourceHeader = nil;
  650. if (request.sourceCopyFrom) {
  651. copySourceHeader = request.sourceCopyFrom;
  652. } else {
  653. if (![request.sourceBucketName oss_isNotEmpty]) {
  654. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain code:OSSClientErrorCodeInvalidArgument userInfo:@{NSLocalizedDescriptionKey: @"sourceBucketName should not be empty!"}];
  655. return [OSSTask taskWithError:error];
  656. }
  657. if (![request.sourceObjectKey oss_isNotEmpty]) {
  658. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain code:OSSClientErrorCodeInvalidArgument userInfo:@{NSLocalizedDescriptionKey: @"sourceObjectKey should not be empty!"}];
  659. return [OSSTask taskWithError:error];
  660. }
  661. copySourceHeader = [NSString stringWithFormat:@"/%@/%@",request.bucketName, request.sourceObjectKey.oss_urlEncodedString];
  662. }
  663. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  664. NSMutableDictionary * headerParams = [NSMutableDictionary dictionaryWithDictionary:request.objectMeta];
  665. [headerParams oss_setObject:copySourceHeader forKey:OSSHttpHeaderCopySource];
  666. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeCopyObject];
  667. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  668. neededMsg.endpoint = self.endpoint;
  669. neededMsg.httpMethod = OSSHTTPMethodPUT;
  670. neededMsg.bucketName = request.bucketName;
  671. neededMsg.objectKey = request.objectKey;
  672. neededMsg.contentType = request.contentType;
  673. neededMsg.contentMd5 = request.contentMd5;
  674. neededMsg.headerParams = headerParams;
  675. neededMsg.contentSHA1 = request.contentSHA1;
  676. requestDelegate.allNeededMessage = neededMsg;
  677. requestDelegate.operType = OSSOperationTypeCopyObject;
  678. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  679. }
  680. - (OSSTask *)putSymlink:(OSSPutSymlinkRequest *)request {
  681. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  682. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypePutSymlink];
  683. NSMutableDictionary *headerFields = [NSMutableDictionary dictionary];
  684. [headerFields oss_setObject:[request.targetObjectName oss_urlEncodedString] forKey:OSSHttpHeaderSymlinkTarget];
  685. if (request.objectMeta) {
  686. [headerFields addEntriesFromDictionary:request.objectMeta];
  687. }
  688. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  689. neededMsg.endpoint = self.endpoint;
  690. neededMsg.httpMethod = OSSHTTPMethodPUT;
  691. neededMsg.bucketName = request.bucketName;
  692. neededMsg.objectKey = request.objectKey;
  693. neededMsg.params = request.requestParams;
  694. neededMsg.headerParams = headerFields;
  695. requestDelegate.allNeededMessage = neededMsg;
  696. requestDelegate.operType = OSSOperationTypePutSymlink;
  697. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  698. }
  699. - (OSSTask *)getSymlink:(OSSGetSymlinkRequest *)request {
  700. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  701. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeGetSymlink];
  702. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  703. neededMsg.endpoint = self.endpoint;
  704. neededMsg.httpMethod = OSSHTTPMethodGET;
  705. neededMsg.bucketName = request.bucketName;
  706. neededMsg.objectKey = request.objectKey;
  707. neededMsg.params = request.requestParams;
  708. requestDelegate.allNeededMessage = neededMsg;
  709. requestDelegate.operType = OSSOperationTypeGetSymlink;
  710. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  711. }
  712. - (OSSTask *)restoreObject:(OSSRestoreObjectRequest *)request {
  713. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  714. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeRestoreObject];
  715. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  716. neededMsg.endpoint = self.endpoint;
  717. neededMsg.httpMethod = OSSHTTPMethodPOST;
  718. neededMsg.bucketName = request.bucketName;
  719. neededMsg.objectKey = request.objectKey;
  720. neededMsg.params = request.requestParams;
  721. requestDelegate.allNeededMessage = neededMsg;
  722. requestDelegate.operType = OSSOperationTypeRestoreObject;
  723. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  724. }
  725. @end
  726. @implementation OSSClient (MultipartUpload)
  727. - (OSSTask *)listMultipartUploads:(OSSListMultipartUploadsRequest *)request {
  728. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  729. NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithDictionary:[request requestParams]];
  730. [params oss_setObject:@"" forKey:@"uploads"];
  731. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeListMultipartUploads];
  732. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  733. neededMsg.endpoint = self.endpoint;
  734. neededMsg.httpMethod = OSSHTTPMethodGET;
  735. neededMsg.bucketName = request.bucketName;
  736. neededMsg.params = params;
  737. requestDelegate.allNeededMessage = neededMsg;
  738. requestDelegate.operType = OSSOperationTypeListMultipartUploads;
  739. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  740. }
  741. - (OSSTask *)multipartUploadInit:(OSSInitMultipartUploadRequest *)request {
  742. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  743. NSMutableDictionary * headerParams = [NSMutableDictionary dictionaryWithDictionary:request.objectMeta];
  744. [headerParams oss_setObject:request.contentDisposition forKey:OSSHttpHeaderContentDisposition];
  745. [headerParams oss_setObject:request.contentEncoding forKey:OSSHttpHeaderContentEncoding];
  746. [headerParams oss_setObject:request.expires forKey:OSSHttpHeaderExpires];
  747. [headerParams oss_setObject:request.cacheControl forKey:OSSHttpHeaderCacheControl];
  748. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  749. [params oss_setObject:@"" forKey:@"uploads"];
  750. if (request.sequential) {
  751. [params oss_setObject:@"" forKey:@"sequential"];
  752. }
  753. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeInitMultipartUpload];
  754. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  755. neededMsg.endpoint = self.endpoint;
  756. neededMsg.httpMethod = OSSHTTPMethodPOST;
  757. neededMsg.bucketName = request.bucketName;
  758. neededMsg.objectKey = request.objectKey;
  759. neededMsg.contentType = request.contentType;
  760. neededMsg.params = params;
  761. neededMsg.headerParams = headerParams;
  762. requestDelegate.allNeededMessage = neededMsg;
  763. requestDelegate.operType = OSSOperationTypeInitMultipartUpload;
  764. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  765. }
  766. - (OSSTask *)uploadPart:(OSSUploadPartRequest *)request {
  767. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  768. NSMutableDictionary * params = [NSMutableDictionary dictionary];
  769. [params oss_setObject:[@(request.partNumber) stringValue] forKey:@"partNumber"];
  770. [params oss_setObject:request.uploadId forKey:@"uploadId"];
  771. [self enableCRC64WithFlag:request.crcFlag requestDelegate:requestDelegate];
  772. if (request.uploadPartData) {
  773. requestDelegate.uploadingData = request.uploadPartData;
  774. if (requestDelegate.crc64Verifiable)
  775. {
  776. NSMutableData *mutableData = [NSMutableData dataWithData:request.uploadPartData];
  777. requestDelegate.contentCRC = [NSString stringWithFormat:@"%llu",[mutableData oss_crc64]];
  778. }
  779. }
  780. if (request.uploadPartFileURL) {
  781. requestDelegate.uploadingFileURL = request.uploadPartFileURL;
  782. }
  783. if (request.uploadPartProgress) {
  784. requestDelegate.uploadProgress = request.uploadPartProgress;
  785. }
  786. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeUploadPart];
  787. responseParser.crc64Verifiable = requestDelegate.crc64Verifiable;
  788. requestDelegate.responseParser = responseParser;
  789. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  790. neededMsg.endpoint = self.endpoint;
  791. neededMsg.httpMethod = OSSHTTPMethodPUT;
  792. neededMsg.bucketName = request.bucketName;
  793. neededMsg.objectKey = request.objectkey;
  794. neededMsg.contentMd5 = request.contentMd5;
  795. neededMsg.params = params;
  796. neededMsg.contentSHA1 = request.contentSHA1;
  797. requestDelegate.allNeededMessage = neededMsg;
  798. requestDelegate.operType = OSSOperationTypeUploadPart;
  799. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  800. }
  801. - (OSSTask *)completeMultipartUpload:(OSSCompleteMultipartUploadRequest *)request
  802. {
  803. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  804. NSMutableDictionary * headerParams = [NSMutableDictionary dictionary];
  805. if (request.partInfos) {
  806. requestDelegate.uploadingData = [OSSUtil constructHttpBodyFromPartInfos:request.partInfos];
  807. }
  808. [headerParams oss_setObject:[request.callbackParam base64JsonString] forKey:OSSHttpHeaderXOSSCallback];
  809. [headerParams oss_setObject:[request.callbackVar base64JsonString] forKey:OSSHttpHeaderXOSSCallbackVar];
  810. if (request.completeMetaHeader) {
  811. [headerParams addEntriesFromDictionary:request.completeMetaHeader];
  812. }
  813. NSMutableDictionary * params = [NSMutableDictionary dictionaryWithObjectsAndKeys:request.uploadId, @"uploadId", nil];
  814. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeCompleteMultipartUpload];
  815. responseParser.crc64Verifiable = requestDelegate.crc64Verifiable;
  816. requestDelegate.responseParser = responseParser;
  817. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  818. neededMsg.endpoint = self.endpoint;
  819. neededMsg.httpMethod = OSSHTTPMethodPOST;
  820. neededMsg.bucketName = request.bucketName;
  821. neededMsg.objectKey = request.objectKey;
  822. neededMsg.contentMd5 = request.contentMd5;
  823. neededMsg.headerParams = headerParams;
  824. neededMsg.params = params;
  825. neededMsg.contentSHA1 = request.contentSHA1;
  826. requestDelegate.allNeededMessage = neededMsg;
  827. requestDelegate.operType = OSSOperationTypeCompleteMultipartUpload;
  828. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  829. }
  830. - (OSSTask *)listParts:(OSSListPartsRequest *)request {
  831. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  832. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  833. [params oss_setObject: request.uploadId forKey: @"uploadId"];
  834. [params oss_setObject: [NSString stringWithFormat:@"%d",request.partNumberMarker] forKey: @"part-number-marker"];
  835. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeListMultipart];
  836. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  837. neededMsg.endpoint = self.endpoint;
  838. neededMsg.httpMethod = OSSHTTPMethodGET;
  839. neededMsg.bucketName = request.bucketName;
  840. neededMsg.objectKey = request.objectKey;
  841. neededMsg.params = params;
  842. requestDelegate.allNeededMessage = neededMsg;
  843. requestDelegate.operType = OSSOperationTypeListMultipart;
  844. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  845. }
  846. - (OSSTask *)abortMultipartUpload:(OSSAbortMultipartUploadRequest *)request {
  847. OSSNetworkingRequestDelegate * requestDelegate = request.requestDelegate;
  848. NSMutableDictionary * params = [NSMutableDictionary dictionaryWithObjectsAndKeys:request.uploadId, @"uploadId", nil];
  849. requestDelegate.responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeAbortMultipartUpload];
  850. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  851. neededMsg.endpoint = self.endpoint;
  852. neededMsg.httpMethod = OSSHTTPMethodDELETE;
  853. neededMsg.bucketName = request.bucketName;
  854. neededMsg.objectKey = request.objectKey;
  855. neededMsg.params = params;
  856. requestDelegate.allNeededMessage = neededMsg;
  857. requestDelegate.operType = OSSOperationTypeAbortMultipartUpload;
  858. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  859. }
  860. - (OSSTask *)abortResumableMultipartUpload:(OSSResumableUploadRequest *)request
  861. {
  862. return [self abortMultipartUpload:request sequential:NO resumable:YES];
  863. }
  864. - (OSSTask *)abortMultipartUpload:(OSSMultipartUploadRequest *)request sequential:(BOOL)sequential resumable:(BOOL)resumable {
  865. OSSTask *errorTask = nil;
  866. if(resumable) {
  867. OSSResumableUploadRequest *resumableRequest = (OSSResumableUploadRequest *)request;
  868. NSString *nameInfoString = [NSString stringWithFormat:@"%@%@%@%lu",request.md5String, resumableRequest.bucketName, resumableRequest.objectKey, (unsigned long)resumableRequest.partSize];
  869. if (sequential) {
  870. nameInfoString = [nameInfoString stringByAppendingString:kClientRecordNameWithSequentialSuffix];
  871. }
  872. if (request.crcFlag == OSSRequestCRCOpen) {
  873. nameInfoString = [nameInfoString stringByAppendingString:kClientRecordNameWithCRC64Suffix];
  874. }
  875. NSData *data = [nameInfoString dataUsingEncoding:NSUTF8StringEncoding];
  876. NSString *recordFileName = [OSSUtil dataMD5String:data];
  877. NSString *recordFilePath = [NSString stringWithFormat:@"%@/%@",resumableRequest.recordDirectoryPath,recordFileName];
  878. NSFileManager *fileManager = [NSFileManager defaultManager];
  879. NSString *partInfosFilePath = [[[NSString oss_documentDirectory] stringByAppendingPathComponent:kClientRecordNameWithCommonPrefix] stringByAppendingPathComponent:resumableRequest.uploadId];
  880. if([fileManager fileExistsAtPath:recordFilePath])
  881. {
  882. NSError *error;
  883. if (![fileManager removeItemAtPath:recordFilePath error:&error])
  884. {
  885. OSSLogDebug(@"[OSSSDKError]: %@", error);
  886. }
  887. }
  888. if ([fileManager fileExistsAtPath:partInfosFilePath]) {
  889. NSError *error;
  890. if (![fileManager removeItemAtPath:partInfosFilePath error:&error])
  891. {
  892. OSSLogDebug(@"[OSSSDKError]: %@", error);
  893. }
  894. }
  895. OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
  896. abort.bucketName = request.bucketName;
  897. abort.objectKey = request.objectKey;
  898. if (request.uploadId) {
  899. abort.uploadId = request.uploadId;
  900. } else {
  901. abort.uploadId = [[NSString alloc] initWithData:[[NSFileHandle fileHandleForReadingAtPath:recordFilePath] readDataToEndOfFile] encoding:NSUTF8StringEncoding];
  902. }
  903. errorTask = [self abortMultipartUpload:abort];
  904. }else
  905. {
  906. OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
  907. abort.bucketName = request.bucketName;
  908. abort.objectKey = request.objectKey;
  909. abort.uploadId = request.uploadId;
  910. errorTask = [self abortMultipartUpload:abort];
  911. }
  912. return errorTask;
  913. }
  914. - (OSSTask *)multipartUpload:(OSSMultipartUploadRequest *)request {
  915. return [self multipartUpload: request resumable: NO sequential: NO];
  916. }
  917. - (OSSTask *)processCompleteMultipartUpload:(OSSMultipartUploadRequest *)request partInfos:(NSArray<OSSPartInfo *> *)partInfos clientCrc64:(uint64_t)clientCrc64 recordFilePath:(NSString *)recordFilePath localPartInfosPath:(NSString *)localPartInfosPath
  918. {
  919. OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
  920. complete.bucketName = request.bucketName;
  921. complete.objectKey = request.objectKey;
  922. complete.uploadId = request.uploadId;
  923. complete.partInfos = partInfos;
  924. complete.crcFlag = request.crcFlag;
  925. complete.contentSHA1 = request.contentSHA1;
  926. if (request.completeMetaHeader != nil) {
  927. complete.completeMetaHeader = request.completeMetaHeader;
  928. }
  929. if (request.callbackParam != nil) {
  930. complete.callbackParam = request.callbackParam;
  931. }
  932. if (request.callbackVar != nil) {
  933. complete.callbackVar = request.callbackVar;
  934. }
  935. OSSTask * completeTask = [self completeMultipartUpload:complete];
  936. [completeTask waitUntilFinished];
  937. if (completeTask.error) {
  938. OSSLogVerbose(@"completeTask.error %@: ",completeTask.error);
  939. return completeTask;
  940. } else
  941. {
  942. if(recordFilePath && [[NSFileManager defaultManager] fileExistsAtPath:recordFilePath])
  943. {
  944. NSError *deleteError;
  945. if (![[NSFileManager defaultManager] removeItemAtPath:recordFilePath error:&deleteError])
  946. {
  947. OSSLogError(@"delete localUploadIdPath failed!Error: %@",deleteError);
  948. }
  949. }
  950. if (localPartInfosPath && [[NSFileManager defaultManager] fileExistsAtPath:localPartInfosPath])
  951. {
  952. NSError *deleteError;
  953. if (![[NSFileManager defaultManager] removeItemAtPath:localPartInfosPath error:&deleteError])
  954. {
  955. OSSLogError(@"delete localPartInfosPath failed!Error: %@",deleteError);
  956. }
  957. }
  958. OSSCompleteMultipartUploadResult * completeResult = completeTask.result;
  959. if (complete.crcFlag == OSSRequestCRCOpen && completeResult.remoteCRC64ecma)
  960. {
  961. uint64_t remote_crc64 = 0;
  962. NSScanner *scanner = [NSScanner scannerWithString:completeResult.remoteCRC64ecma];
  963. if ([scanner scanUnsignedLongLong:&remote_crc64])
  964. {
  965. OSSLogVerbose(@"resumableUpload local_crc64 %llu",clientCrc64);
  966. OSSLogVerbose(@"resumableUpload remote_crc64 %llu", remote_crc64);
  967. if (remote_crc64 != clientCrc64)
  968. {
  969. NSString *errorMessage = [NSString stringWithFormat:@"local_crc64(%llu) is not equal to remote_crc64(%llu)!",clientCrc64,remote_crc64];
  970. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  971. code:OSSClientErrorCodeInvalidCRC
  972. userInfo:@{OSSErrorMessageTOKEN:errorMessage}];
  973. return [OSSTask taskWithError:error];
  974. }
  975. }
  976. }
  977. OSSResumableUploadResult * result = [OSSResumableUploadResult new];
  978. result.requestId = completeResult.requestId;
  979. result.httpResponseCode = completeResult.httpResponseCode;
  980. result.httpResponseHeaderFields = completeResult.httpResponseHeaderFields;
  981. result.serverReturnJsonString = completeResult.serverReturnJsonString;
  982. result.remoteCRC64ecma = completeResult.remoteCRC64ecma;
  983. return [OSSTask taskWithResult:result];
  984. }
  985. }
  986. - (OSSTask *)resumableUpload:(OSSResumableUploadRequest *)request
  987. {
  988. return [self multipartUpload: request resumable: YES sequential: NO];
  989. }
  990. - (OSSTask *)processListPartsWithObjectKey:(nonnull NSString *)objectKey bucket:(nonnull NSString *)bucket uploadId:(NSString * _Nonnull *)uploadId uploadedParts:(nonnull NSMutableArray *)uploadedParts uploadedLength:(NSUInteger *)uploadedLength totalSize:(unsigned long long)totalSize partSize:(NSUInteger)partSize
  991. {
  992. BOOL isTruncated = NO;
  993. int nextPartNumberMarker = 0;
  994. do {
  995. OSSListPartsRequest * listParts = [OSSListPartsRequest new];
  996. listParts.bucketName = bucket;
  997. listParts.objectKey = objectKey;
  998. listParts.uploadId = *uploadId;
  999. listParts.partNumberMarker = nextPartNumberMarker;
  1000. OSSTask * listPartsTask = [self listParts:listParts];
  1001. [listPartsTask waitUntilFinished];
  1002. if (listPartsTask.error)
  1003. {
  1004. isTruncated = NO;
  1005. [uploadedParts removeAllObjects];
  1006. if ([listPartsTask.error.domain isEqualToString: OSSServerErrorDomain] && labs(listPartsTask.error.code) == 404)
  1007. {
  1008. OSSLogVerbose(@"local record existes but the remote record is deleted");
  1009. *uploadId = nil;
  1010. } else
  1011. {
  1012. return listPartsTask;
  1013. }
  1014. }
  1015. else
  1016. {
  1017. OSSListPartsResult *res = listPartsTask.result;
  1018. isTruncated = res.isTruncated;
  1019. nextPartNumberMarker = res.nextPartNumberMarker;
  1020. OSSLogVerbose(@"resumableUpload listpart ok");
  1021. if (res.parts.count > 0) {
  1022. [uploadedParts addObjectsFromArray:res.parts];
  1023. }
  1024. }
  1025. } while (isTruncated);
  1026. __block NSUInteger firstPartSize = 0;
  1027. __block NSUInteger bUploadedLength = 0;
  1028. [uploadedParts enumerateObjectsUsingBlock:^(NSDictionary *part, NSUInteger idx, BOOL * _Nonnull stop) {
  1029. unsigned long long iPartSize = 0;
  1030. NSString *partSizeString = [part objectForKey:OSSSizeXMLTOKEN];
  1031. NSScanner *scanner = [NSScanner scannerWithString:partSizeString];
  1032. [scanner scanUnsignedLongLong:&iPartSize];
  1033. #pragma clang diagnostic push
  1034. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1035. bUploadedLength += iPartSize;
  1036. if (idx == 0)
  1037. {
  1038. firstPartSize = iPartSize;
  1039. }
  1040. #pragma clang diagnostic pop
  1041. }];
  1042. *uploadedLength = bUploadedLength;
  1043. if (totalSize < bUploadedLength)
  1044. {
  1045. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  1046. code:OSSClientErrorCodeCannotResumeUpload
  1047. userInfo:@{OSSErrorMessageTOKEN: @"The uploading file is inconsistent with before"}];
  1048. return [OSSTask taskWithError: error];
  1049. }
  1050. else if (firstPartSize != 0 && firstPartSize != partSize && totalSize != firstPartSize)
  1051. {
  1052. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  1053. code:OSSClientErrorCodeCannotResumeUpload
  1054. userInfo:@{OSSErrorMessageTOKEN: @"The part size setting is inconsistent with before"}];
  1055. return [OSSTask taskWithError: error];
  1056. }
  1057. return nil;
  1058. }
  1059. - (OSSTask *)processResumableInitMultipartUpload:(OSSInitMultipartUploadRequest *)request recordFilePath:(NSString *)recordFilePath
  1060. {
  1061. OSSTask *task = [self multipartUploadInit:request];
  1062. [task waitUntilFinished];
  1063. if(task.result && [recordFilePath oss_isNotEmpty])
  1064. {
  1065. OSSInitMultipartUploadResult *result = task.result;
  1066. if (![result.uploadId oss_isNotEmpty])
  1067. {
  1068. NSString *errorMessage = [NSString stringWithFormat:@"Can not get uploadId!"];
  1069. NSError *error = [NSError errorWithDomain:OSSServerErrorDomain
  1070. code:OSSClientErrorCodeNilUploadid userInfo:@{OSSErrorMessageTOKEN: errorMessage}];
  1071. return [OSSTask taskWithError:error];
  1072. }
  1073. NSFileManager *defaultFM = [NSFileManager defaultManager];
  1074. if (![defaultFM fileExistsAtPath:recordFilePath])
  1075. {
  1076. if (![defaultFM createFileAtPath:recordFilePath contents:nil attributes:nil]) {
  1077. NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
  1078. code:OSSClientErrorCodeFileCantWrite
  1079. userInfo:@{OSSErrorMessageTOKEN: @"uploadId for this task can't be stored persistentially!"}];
  1080. OSSLogDebug(@"[Error]: %@", error);
  1081. return [OSSTask taskWithError:error];
  1082. }
  1083. }
  1084. NSFileHandle * write = [NSFileHandle fileHandleForWritingAtPath:recordFilePath];
  1085. [write writeData:[result.uploadId dataUsingEncoding:NSUTF8StringEncoding]];
  1086. [write closeFile];
  1087. }
  1088. return task;
  1089. }
  1090. - (OSSTask *)upload:(OSSMultipartUploadRequest *)request
  1091. uploadIndex:(NSMutableArray *)alreadyUploadIndex
  1092. uploadPart:(NSMutableArray *)alreadyUploadPart
  1093. count:(NSUInteger)partCout
  1094. uploadedLength:(NSUInteger *)uploadedLength
  1095. fileSize:(unsigned long long)uploadFileSize
  1096. {
  1097. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  1098. [queue setMaxConcurrentOperationCount: 5];
  1099. NSObject *localLock = [[NSObject alloc] init];
  1100. OSSRequestCRCFlag crcFlag = request.crcFlag;
  1101. __block OSSTask *errorTask;
  1102. __block NSMutableDictionary *localPartInfos = nil;
  1103. if (crcFlag == OSSRequestCRCOpen) {
  1104. localPartInfos = [self localPartInfosDictoryWithUploadId:request.uploadId];
  1105. }
  1106. if (!localPartInfos) {
  1107. localPartInfos = [NSMutableDictionary dictionary];
  1108. }
  1109. NSError *readError;
  1110. NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingFromURL:request.uploadingFileURL error:&readError];
  1111. if (readError) {
  1112. return [OSSTask taskWithError: readError];
  1113. }
  1114. NSData * uploadPartData;
  1115. NSInteger realPartLength = request.partSize;
  1116. __block BOOL hasError = NO;
  1117. for (NSUInteger idx = 1; idx <= partCout; idx++)
  1118. {
  1119. if (request.isCancelled)
  1120. {
  1121. [queue cancelAllOperations];
  1122. break;
  1123. }
  1124. if ([alreadyUploadIndex containsObject:@(idx)])
  1125. {
  1126. continue;
  1127. }
  1128. // while operationCount >= 5,the loop will stay here
  1129. while (queue.operationCount >= 5) {
  1130. [NSThread sleepForTimeInterval: 0.15f];
  1131. }
  1132. if (idx == partCout) {
  1133. #pragma clang diagnostic push
  1134. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1135. realPartLength = uploadFileSize - request.partSize * (idx - 1);
  1136. #pragma clang diagnostic pop
  1137. }
  1138. @autoreleasepool
  1139. {
  1140. [fileHande seekToFileOffset: request.partSize * (idx - 1)];
  1141. uploadPartData = [fileHande readDataOfLength:realPartLength];
  1142. NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
  1143. OSSTask *uploadPartErrorTask = nil;
  1144. [self executePartUpload:request
  1145. totalBytesExpectedToSend:uploadFileSize
  1146. totalBytesSent:uploadedLength
  1147. index:idx
  1148. partData:uploadPartData
  1149. alreadyUploadPart:alreadyUploadPart
  1150. localParts:localPartInfos
  1151. errorTask:&uploadPartErrorTask];
  1152. if (uploadPartErrorTask != nil) {
  1153. @synchronized(localLock) {
  1154. if (!hasError) {
  1155. hasError = YES;
  1156. errorTask = uploadPartErrorTask;
  1157. }
  1158. }
  1159. uploadPartErrorTask = nil;
  1160. }
  1161. }];
  1162. [queue addOperation:operation];
  1163. }
  1164. }
  1165. [fileHande closeFile];
  1166. [queue waitUntilAllOperationsAreFinished];
  1167. localLock = nil;
  1168. if (!errorTask && request.isCancelled) {
  1169. errorTask = [OSSTask taskWithError:[OSSClient cancelError]];
  1170. }
  1171. return errorTask;
  1172. }
  1173. - (void)executePartUpload:(OSSMultipartUploadRequest *)request totalBytesExpectedToSend:(unsigned long long)totalBytesExpectedToSend totalBytesSent:(NSUInteger *)totalBytesSent index:(NSUInteger)idx partData:(NSData *)partData alreadyUploadPart:(NSMutableArray *)uploadedParts localParts:(NSMutableDictionary *)localParts errorTask:(OSSTask **)errorTask
  1174. {
  1175. NSUInteger bytesSent = partData.length;
  1176. OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
  1177. uploadPart.bucketName = request.bucketName;
  1178. uploadPart.objectkey = request.objectKey;
  1179. #pragma clang diagnostic push
  1180. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1181. uploadPart.partNumber = idx;
  1182. #pragma clang diagnostic pop
  1183. uploadPart.uploadId = request.uploadId;
  1184. uploadPart.uploadPartData = partData;
  1185. uploadPart.contentMd5 = [OSSUtil base64Md5ForData:partData];
  1186. uploadPart.crcFlag = request.crcFlag;
  1187. OSSTask * uploadPartTask = [self uploadPart:uploadPart];
  1188. [uploadPartTask waitUntilFinished];
  1189. if (uploadPartTask.error) {
  1190. if (labs(uploadPartTask.error.code) != 409) {
  1191. *errorTask = uploadPartTask;
  1192. }
  1193. } else {
  1194. OSSUploadPartResult * result = uploadPartTask.result;
  1195. OSSPartInfo * partInfo = [OSSPartInfo new];
  1196. #pragma clang diagnostic push
  1197. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1198. partInfo.partNum = idx;
  1199. #pragma clang diagnostic pop
  1200. partInfo.eTag = result.eTag;
  1201. partInfo.size = bytesSent;
  1202. uint64_t crc64OfPart;
  1203. @try {
  1204. NSScanner *scanner = [NSScanner scannerWithString:result.remoteCRC64ecma];
  1205. [scanner scanUnsignedLongLong:&crc64OfPart];
  1206. partInfo.crc64 = crc64OfPart;
  1207. } @catch (NSException *exception) {
  1208. OSSLogError(@"multipart upload error with nil remote crc64!");
  1209. }
  1210. @synchronized(lock){
  1211. [uploadedParts addObject:partInfo];
  1212. if (request.crcFlag == OSSRequestCRCOpen)
  1213. {
  1214. [self processForLocalPartInfos:localParts
  1215. partInfo:partInfo
  1216. uploadId:request.uploadId];
  1217. [self persistencePartInfos:localParts
  1218. withUploadId:request.uploadId];
  1219. }
  1220. *totalBytesSent += bytesSent;
  1221. if (request.uploadProgress)
  1222. {
  1223. request.uploadProgress(bytesSent, *totalBytesSent, totalBytesExpectedToSend);
  1224. }
  1225. }
  1226. }
  1227. }
  1228. - (void)processForLocalPartInfos:(NSMutableDictionary *)localPartInfoDict partInfo:(OSSPartInfo *)partInfo uploadId:(NSString *)uploadId
  1229. {
  1230. NSDictionary *partInfoDict = [partInfo entityToDictionary];
  1231. NSString *keyString = [NSString stringWithFormat:@"%i",partInfo.partNum];
  1232. [localPartInfoDict oss_setObject:partInfoDict forKey:keyString];
  1233. }
  1234. - (OSSTask *)sequentialMultipartUpload:(OSSResumableUploadRequest *)request
  1235. {
  1236. return [self multipartUpload:request resumable:YES sequential:YES];
  1237. }
  1238. - (OSSTask *)multipartUpload:(OSSMultipartUploadRequest *)request resumable:(BOOL)resumable sequential:(BOOL)sequential
  1239. {
  1240. if (resumable) {
  1241. if (![request isKindOfClass:[OSSResumableUploadRequest class]]) {
  1242. NSError *typoError = [NSError errorWithDomain:OSSClientErrorDomain
  1243. code:OSSClientErrorCodeInvalidArgument
  1244. userInfo:@{OSSErrorMessageTOKEN: @"resumable multipart request should use instance of class OSSMultipartUploadRequest!"}];
  1245. return [OSSTask taskWithError: typoError];
  1246. }
  1247. }
  1248. [self checkRequestCrc64Setting:request];
  1249. OSSTask *preTask = [self preChecksForRequest:request];
  1250. if (preTask) {
  1251. return preTask;
  1252. }
  1253. return [[OSSTask taskWithResult:nil] continueWithExecutor:self.ossOperationExecutor withBlock:^id(OSSTask *task) {
  1254. __block NSUInteger uploadedLength = 0;
  1255. uploadedLength = 0;
  1256. __block OSSTask * errorTask;
  1257. __block NSString *uploadId;
  1258. NSError *error;
  1259. unsigned long long uploadFileSize = [self getSizeWithFilePath:request.uploadingFileURL.path error:&error];
  1260. if (error) {
  1261. return [OSSTask taskWithError:error];
  1262. }
  1263. NSUInteger partCount = [self judgePartSizeForMultipartRequest:request fileSize:uploadFileSize];
  1264. if (partCount > 1 && request.partSize < 102400) {
  1265. NSError *checkPartSizeError = [NSError errorWithDomain:OSSClientErrorDomain
  1266. code:OSSClientErrorCodeInvalidArgument
  1267. userInfo:@{OSSErrorMessageTOKEN: @"Part size must be greater than equal to 100KB"}];
  1268. return [OSSTask taskWithError:checkPartSizeError];
  1269. }
  1270. if (request.isCancelled) {
  1271. return [OSSTask taskWithError:[OSSClient cancelError]];
  1272. }
  1273. NSString *recordFilePath = nil;
  1274. NSMutableArray * uploadedPart = [NSMutableArray array];
  1275. NSString *localPartInfosPath = nil;
  1276. NSDictionary *localPartInfos = nil;
  1277. NSMutableArray<OSSPartInfo *> *uploadedPartInfos = [NSMutableArray array];
  1278. NSMutableArray * alreadyUploadIndex = [NSMutableArray array];
  1279. if (resumable) {
  1280. OSSResumableUploadRequest *resumableRequest = (OSSResumableUploadRequest *)request;
  1281. NSString *recordDirectoryPath = resumableRequest.recordDirectoryPath;
  1282. request.md5String = [OSSUtil fileMD5String:request.uploadingFileURL.path];
  1283. if ([recordDirectoryPath oss_isNotEmpty])
  1284. {
  1285. uploadId = [self readUploadIdForRequest:resumableRequest recordFilePath:&recordFilePath sequential:sequential];
  1286. OSSLogVerbose(@"local uploadId: %@,recordFilePath: %@",uploadId, recordFilePath);
  1287. }
  1288. if([uploadId oss_isNotEmpty])
  1289. {
  1290. localPartInfosPath = [[[NSString oss_documentDirectory] stringByAppendingPathComponent:kClientRecordNameWithCommonPrefix] stringByAppendingPathComponent:uploadId];
  1291. localPartInfos = [[NSDictionary alloc] initWithContentsOfFile:localPartInfosPath];
  1292. OSSTask *listPartTask = [self processListPartsWithObjectKey:request.objectKey
  1293. bucket:request.bucketName
  1294. uploadId:&uploadId
  1295. uploadedParts:uploadedPart
  1296. uploadedLength:&uploadedLength
  1297. totalSize:uploadFileSize
  1298. partSize:request.partSize];
  1299. if (listPartTask.error)
  1300. {
  1301. return listPartTask;
  1302. }
  1303. }
  1304. [uploadedPart enumerateObjectsUsingBlock:^(NSDictionary *partInfo, NSUInteger idx, BOOL * _Nonnull stop) {
  1305. unsigned long long remotePartNumber = 0;
  1306. NSString *partNumberString = [partInfo objectForKey: OSSPartNumberXMLTOKEN];
  1307. NSScanner *scanner = [NSScanner scannerWithString: partNumberString];
  1308. [scanner scanUnsignedLongLong: &remotePartNumber];
  1309. NSString *remotePartEtag = [partInfo objectForKey:OSSETagXMLTOKEN];
  1310. unsigned long long remotePartSize = 0;
  1311. NSString *partSizeString = [partInfo objectForKey:OSSSizeXMLTOKEN];
  1312. scanner = [NSScanner scannerWithString:partSizeString];
  1313. [scanner scanUnsignedLongLong:&remotePartSize];
  1314. #pragma clang diagnostic push
  1315. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1316. OSSPartInfo * info = [[OSSPartInfo alloc] init];
  1317. info.partNum = remotePartNumber;
  1318. info.size = remotePartSize;
  1319. info.eTag = remotePartEtag;
  1320. #pragma clang diagnostic pop
  1321. NSDictionary *tPartInfo = [localPartInfos objectForKey: [@(remotePartNumber) stringValue]];
  1322. info.crc64 = [tPartInfo[@"crc64"] unsignedLongLongValue];
  1323. [uploadedPartInfos addObject:info];
  1324. [alreadyUploadIndex addObject:@(remotePartNumber)];
  1325. }];
  1326. if ([alreadyUploadIndex count] > 0 && request.uploadProgress && uploadFileSize) {
  1327. request.uploadProgress(0, uploadedLength, uploadFileSize);
  1328. }
  1329. }
  1330. if (![uploadId oss_isNotEmpty]) {
  1331. OSSInitMultipartUploadRequest *initRequest = [OSSInitMultipartUploadRequest new];
  1332. initRequest.bucketName = request.bucketName;
  1333. initRequest.objectKey = request.objectKey;
  1334. initRequest.contentType = request.contentType;
  1335. initRequest.objectMeta = request.completeMetaHeader;
  1336. initRequest.sequential = sequential;
  1337. initRequest.crcFlag = request.crcFlag;
  1338. OSSTask *task = [self processResumableInitMultipartUpload:initRequest
  1339. recordFilePath:recordFilePath];
  1340. if (task.error)
  1341. {
  1342. return task;
  1343. }
  1344. OSSInitMultipartUploadResult *initResult = (OSSInitMultipartUploadResult *)task.result;
  1345. uploadId = initResult.uploadId;
  1346. }
  1347. request.uploadId = uploadId;
  1348. localPartInfosPath = [[[NSString oss_documentDirectory] stringByAppendingPathComponent:kClientRecordNameWithCommonPrefix] stringByAppendingPathComponent:uploadId];
  1349. if (request.isCancelled)
  1350. {
  1351. if(resumable)
  1352. {
  1353. OSSResumableUploadRequest *resumableRequest = (OSSResumableUploadRequest *)request;
  1354. if (resumableRequest.deleteUploadIdOnCancelling) {
  1355. OSSTask *abortTask = [self abortMultipartUpload:request sequential:sequential resumable:resumable];
  1356. [abortTask waitUntilFinished];
  1357. }
  1358. }
  1359. return [OSSTask taskWithError:[OSSClient cancelError]];
  1360. }
  1361. if (sequential) {
  1362. errorTask = [self sequentialUpload:request
  1363. uploadIndex:alreadyUploadIndex
  1364. uploadPart:uploadedPartInfos
  1365. count:partCount
  1366. uploadedLength:&uploadedLength
  1367. fileSize:uploadFileSize];
  1368. } else {
  1369. errorTask = [self upload:request
  1370. uploadIndex:alreadyUploadIndex
  1371. uploadPart:uploadedPartInfos
  1372. count:partCount
  1373. uploadedLength:&uploadedLength
  1374. fileSize:uploadFileSize];
  1375. }
  1376. if(errorTask.error)
  1377. {
  1378. OSSTask *abortTask;
  1379. if(resumable)
  1380. {
  1381. OSSResumableUploadRequest *resumableRequest = (OSSResumableUploadRequest *)request;
  1382. if (resumableRequest.deleteUploadIdOnCancelling || errorTask.error.code == OSSClientErrorCodeFileCantWrite) {
  1383. abortTask = [self abortMultipartUpload:request sequential:sequential resumable:resumable];
  1384. }
  1385. }else
  1386. {
  1387. abortTask =[self abortMultipartUpload:request sequential:sequential resumable:resumable];
  1388. }
  1389. [abortTask waitUntilFinished];
  1390. return errorTask;
  1391. }
  1392. [uploadedPartInfos sortUsingComparator:^NSComparisonResult(OSSPartInfo *part1,OSSPartInfo* part2) {
  1393. if(part1.partNum < part2.partNum){
  1394. return NSOrderedAscending;
  1395. }else if(part1.partNum > part2.partNum){
  1396. return NSOrderedDescending;
  1397. }else{
  1398. return NSOrderedSame;
  1399. }
  1400. }];
  1401. // 如果开启了crc64的校验
  1402. uint64_t local_crc64 = 0;
  1403. if (request.crcFlag == OSSRequestCRCOpen)
  1404. {
  1405. for (NSUInteger index = 0; index< uploadedPartInfos.count; index++)
  1406. {
  1407. uint64_t partCrc64 = uploadedPartInfos[index].crc64;
  1408. int64_t partSize = uploadedPartInfos[index].size;
  1409. #pragma clang diagnostic push
  1410. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1411. local_crc64 = [OSSUtil crc64ForCombineCRC1:local_crc64 CRC2:partCrc64 length:partSize];
  1412. #pragma clang diagnostic pop
  1413. }
  1414. }
  1415. return [self processCompleteMultipartUpload:request
  1416. partInfos:uploadedPartInfos
  1417. clientCrc64:local_crc64
  1418. recordFilePath:recordFilePath
  1419. localPartInfosPath:localPartInfosPath];
  1420. }];
  1421. }
  1422. - (OSSTask *)sequentialUpload:(OSSMultipartUploadRequest *)request
  1423. uploadIndex:(NSMutableArray *)alreadyUploadIndex
  1424. uploadPart:(NSMutableArray *)alreadyUploadPart
  1425. count:(NSUInteger)partCout
  1426. uploadedLength:(NSUInteger *)uploadedLength
  1427. fileSize:(unsigned long long)uploadFileSize
  1428. {
  1429. OSSRequestCRCFlag crcFlag = request.crcFlag;
  1430. __block OSSTask *errorTask;
  1431. __block NSMutableDictionary *localPartInfos = nil;
  1432. if (crcFlag == OSSRequestCRCOpen) {
  1433. localPartInfos = [self localPartInfosDictoryWithUploadId:request.uploadId];
  1434. }
  1435. if (!localPartInfos) {
  1436. localPartInfos = [NSMutableDictionary dictionary];
  1437. }
  1438. NSError *readError;
  1439. NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingFromURL:request.uploadingFileURL error:&readError];
  1440. if (readError) {
  1441. return [OSSTask taskWithError: readError];
  1442. }
  1443. NSUInteger realPartLength = request.partSize;
  1444. for (int i = 1; i <= partCout; i++) {
  1445. if (errorTask) {
  1446. break;
  1447. }
  1448. if (request.isCancelled) {
  1449. errorTask = [OSSTask taskWithError:[OSSClient cancelError]];
  1450. break;
  1451. }
  1452. if ([alreadyUploadIndex containsObject:@(i)]) {
  1453. continue;
  1454. }
  1455. realPartLength = request.partSize;
  1456. [fileHande seekToFileOffset:request.partSize * (i - 1)];
  1457. if (i == partCout) {
  1458. #pragma clang diagnostic push
  1459. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1460. realPartLength = uploadFileSize - request.partSize * (i - 1);
  1461. #pragma clang diagnostic pop
  1462. }
  1463. NSData *uploadPartData = [fileHande readDataOfLength:realPartLength];
  1464. @autoreleasepool {
  1465. OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
  1466. uploadPart.bucketName = request.bucketName;
  1467. uploadPart.objectkey = request.objectKey;
  1468. uploadPart.partNumber = i;
  1469. uploadPart.uploadId = request.uploadId;
  1470. uploadPart.uploadPartData = uploadPartData;
  1471. uploadPart.contentMd5 = [OSSUtil base64Md5ForData:uploadPartData];
  1472. uploadPart.crcFlag = request.crcFlag;
  1473. OSSTask * uploadPartTask = [self uploadPart:uploadPart];
  1474. [uploadPartTask waitUntilFinished];
  1475. if (uploadPartTask.error) {
  1476. if (labs(uploadPartTask.error.code) != 409) {
  1477. errorTask = uploadPartTask;
  1478. break;
  1479. } else {
  1480. NSDictionary *partDict = uploadPartTask.error.userInfo;
  1481. OSSPartInfo *partInfo = [[OSSPartInfo alloc] init];
  1482. partInfo.eTag = partDict[@"PartEtag"];
  1483. #pragma clang diagnostic push
  1484. #pragma clang diagnostic ignored "-Wshorten-64-to-32"
  1485. partInfo.partNum = [(NSString *)partDict[@"PartNumber"] integerValue];
  1486. partInfo.size = realPartLength;
  1487. #pragma clang diagnostic push
  1488. partInfo.crc64 = [[uploadPartData mutableCopy] oss_crc64];
  1489. [alreadyUploadPart addObject:partInfo];
  1490. }
  1491. } else {
  1492. OSSUploadPartResult * result = uploadPartTask.result;
  1493. OSSPartInfo * partInfo = [OSSPartInfo new];
  1494. partInfo.partNum = i;
  1495. partInfo.eTag = result.eTag;
  1496. partInfo.size = realPartLength;
  1497. uint64_t crc64OfPart;
  1498. @try {
  1499. NSScanner *scanner = [NSScanner scannerWithString:result.remoteCRC64ecma];
  1500. [scanner scanUnsignedLongLong:&crc64OfPart];
  1501. partInfo.crc64 = crc64OfPart;
  1502. } @catch (NSException *exception) {
  1503. OSSLogError(@"multipart upload error with nil remote crc64!");
  1504. }
  1505. [alreadyUploadPart addObject:partInfo];
  1506. if (crcFlag == OSSRequestCRCOpen)
  1507. {
  1508. [self processForLocalPartInfos:localPartInfos
  1509. partInfo:partInfo
  1510. uploadId:request.uploadId];
  1511. [self persistencePartInfos:localPartInfos
  1512. withUploadId:request.uploadId];
  1513. }
  1514. @synchronized(lock) {
  1515. *uploadedLength += realPartLength;
  1516. if (request.uploadProgress)
  1517. {
  1518. request.uploadProgress(realPartLength, *uploadedLength, uploadFileSize);
  1519. }
  1520. }
  1521. }
  1522. }
  1523. }
  1524. [fileHande closeFile];
  1525. return errorTask;
  1526. }
  1527. @end
  1528. @implementation OSSClient (PresignURL)
  1529. - (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
  1530. withObjectKey:(NSString *)objectKey
  1531. withExpirationInterval:(NSTimeInterval)interval {
  1532. return [self presignConstrainURLWithBucketName:bucketName
  1533. withObjectKey:objectKey
  1534. withExpirationInterval:interval
  1535. withParameters:@{}];
  1536. }
  1537. - (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
  1538. withObjectKey:(NSString *)objectKey
  1539. withExpirationInterval:(NSTimeInterval)interval
  1540. withParameters:(NSDictionary *)parameters {
  1541. return [self presignConstrainURLWithBucketName: bucketName
  1542. withObjectKey: objectKey
  1543. httpMethod: @"GET"
  1544. withExpirationInterval: interval
  1545. withParameters: parameters];
  1546. }
  1547. - (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
  1548. withObjectKey:(NSString *)objectKey
  1549. httpMethod:(NSString *)method
  1550. withExpirationInterval:(NSTimeInterval)interval
  1551. withParameters:(NSDictionary *)parameters
  1552. {
  1553. return [[OSSTask taskWithResult:nil] continueWithBlock:^id(OSSTask *task) {
  1554. NSString * resource = [NSString stringWithFormat:@"/%@/%@", bucketName, objectKey];
  1555. NSString * expires = [@((int64_t)[[NSDate oss_clockSkewFixedDate] timeIntervalSince1970] + interval) stringValue];
  1556. NSMutableDictionary * params = [NSMutableDictionary dictionary];
  1557. if (parameters.count > 0) {
  1558. [params addEntriesFromDictionary:parameters];
  1559. }
  1560. NSString * wholeSign = nil;
  1561. OSSFederationToken *token = nil;
  1562. NSError *error = nil;
  1563. if ([self.credentialProvider isKindOfClass:[OSSFederationCredentialProvider class]]) {
  1564. token = [(OSSFederationCredentialProvider *)self.credentialProvider getToken:&error];
  1565. if (error) {
  1566. return [OSSTask taskWithError:error];
  1567. }
  1568. } else if ([self.credentialProvider isKindOfClass:[OSSStsTokenCredentialProvider class]]) {
  1569. token = [(OSSStsTokenCredentialProvider *)self.credentialProvider getToken];
  1570. }
  1571. if ([self.credentialProvider isKindOfClass:[OSSFederationCredentialProvider class]]
  1572. || [self.credentialProvider isKindOfClass:[OSSStsTokenCredentialProvider class]])
  1573. {
  1574. [params oss_setObject:token.tToken forKey:@"security-token"];
  1575. resource = [NSString stringWithFormat:@"%@?%@", resource, [OSSUtil populateSubresourceStringFromParameter:params]];
  1576. NSString * string2sign = [NSString stringWithFormat:@"%@\n\n\n%@\n%@", method, expires, resource];
  1577. wholeSign = [OSSUtil sign:string2sign withToken:token];
  1578. } else {
  1579. NSString * subresource = [OSSUtil populateSubresourceStringFromParameter:params];
  1580. if ([subresource length] > 0) {
  1581. resource = [NSString stringWithFormat:@"%@?%@", resource, [OSSUtil populateSubresourceStringFromParameter:params]];
  1582. }
  1583. NSString * string2sign = [NSString stringWithFormat:@"%@\n\n\n%@\n%@", method, expires, resource];
  1584. wholeSign = [self.credentialProvider sign:string2sign error:&error];
  1585. if (error) {
  1586. return [OSSTask taskWithError:error];
  1587. }
  1588. }
  1589. NSArray * splitResult = [wholeSign componentsSeparatedByString:@":"];
  1590. if ([splitResult count] != 2
  1591. || ![((NSString *)[splitResult objectAtIndex:0]) hasPrefix:@"OSS "]) {
  1592. return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain
  1593. code:OSSClientErrorCodeSignFailed
  1594. userInfo:@{OSSErrorMessageTOKEN: @"the returned signature is invalid"}]];
  1595. }
  1596. NSString * accessKey = [(NSString *)[splitResult objectAtIndex:0] substringFromIndex:4];
  1597. NSString * signature = [splitResult objectAtIndex:1];
  1598. BOOL isPathStyle = false;
  1599. NSURL * endpointURL = [NSURL URLWithString:self.endpoint];
  1600. NSString * host = endpointURL.host;
  1601. NSString * port = @"";
  1602. NSString * path = @"";
  1603. NSString * pathStylePath = @"";
  1604. if ([OSSUtil isOssOriginBucketHost:host]) {
  1605. host = [NSString stringWithFormat:@"%@.%@", bucketName, host];
  1606. } else if ([OSSUtil isIncludeCnameExcludeList:self.clientConfiguration.cnameExcludeList host:host]) {
  1607. if (self.clientConfiguration.isPathStyleAccessEnable) {
  1608. isPathStyle = true;
  1609. } else {
  1610. host = [NSString stringWithFormat:@"%@.%@", bucketName, host];
  1611. }
  1612. } else if ([[OSSIPv6Adapter getInstance] isIPv4Address:host] ||
  1613. [[OSSIPv6Adapter getInstance] isIPv6Address:host]) {
  1614. isPathStyle = true;
  1615. }
  1616. if (endpointURL.port) {
  1617. port = [NSString stringWithFormat:@":%@", endpointURL.port];
  1618. }
  1619. if (self.clientConfiguration.isCustomPathPrefixEnable) {
  1620. path = endpointURL.path;
  1621. }
  1622. if (isPathStyle) {
  1623. pathStylePath = [@"/" stringByAppendingString:bucketName];
  1624. }
  1625. [params oss_setObject:signature forKey:@"Signature"];
  1626. [params oss_setObject:accessKey forKey:@"OSSAccessKeyId"];
  1627. [params oss_setObject:expires forKey:@"Expires"];
  1628. NSString * stringURL = [NSString stringWithFormat:@"%@://%@%@%@%@/%@?%@",
  1629. endpointURL.scheme,
  1630. host,
  1631. port,
  1632. path,
  1633. pathStylePath,
  1634. [OSSUtil encodeURL:objectKey],
  1635. [OSSUtil populateQueryStringFromParameter:params]];
  1636. return [OSSTask taskWithResult:stringURL];
  1637. }];
  1638. }
  1639. - (OSSTask *)presignPublicURLWithBucketName:(NSString *)bucketName
  1640. withObjectKey:(NSString *)objectKey {
  1641. return [self presignPublicURLWithBucketName:bucketName
  1642. withObjectKey:objectKey
  1643. withParameters:@{}];
  1644. }
  1645. - (OSSTask *)presignPublicURLWithBucketName:(NSString *)bucketName
  1646. withObjectKey:(NSString *)objectKey
  1647. withParameters:(NSDictionary *)parameters {
  1648. return [[OSSTask taskWithResult:nil] continueWithBlock:^id(OSSTask *task) {
  1649. BOOL isPathStyle = false;
  1650. NSURL * endpointURL = [NSURL URLWithString:self.endpoint];
  1651. NSString * host = endpointURL.host;
  1652. NSString * port = @"";
  1653. NSString * path = @"";
  1654. NSString * pathStylePath = @"";
  1655. if ([OSSUtil isOssOriginBucketHost:host]) {
  1656. host = [NSString stringWithFormat:@"%@.%@", bucketName, host];
  1657. } else if ([OSSUtil isIncludeCnameExcludeList:self.clientConfiguration.cnameExcludeList host:host]) {
  1658. if (self.clientConfiguration.isPathStyleAccessEnable) {
  1659. isPathStyle = true;
  1660. } else {
  1661. host = [NSString stringWithFormat:@"%@.%@", bucketName, host];
  1662. }
  1663. } else if ([[OSSIPv6Adapter getInstance] isIPv4Address:host] ||
  1664. [[OSSIPv6Adapter getInstance] isIPv6Address:host]) {
  1665. isPathStyle = true;
  1666. }
  1667. if (endpointURL.port) {
  1668. port = [NSString stringWithFormat:@":%@", endpointURL.port];
  1669. }
  1670. if (self.clientConfiguration.isCustomPathPrefixEnable) {
  1671. path = endpointURL.path;
  1672. }
  1673. if (isPathStyle) {
  1674. pathStylePath = [@"/" stringByAppendingString:bucketName];
  1675. }
  1676. if ([parameters count] > 0) {
  1677. NSString * stringURL = [NSString stringWithFormat:@"%@://%@%@%@%@/%@?%@",
  1678. endpointURL.scheme,
  1679. host,
  1680. port,
  1681. path,
  1682. pathStylePath,
  1683. [OSSUtil encodeURL:objectKey],
  1684. [OSSUtil populateQueryStringFromParameter:parameters]];
  1685. return [OSSTask taskWithResult:stringURL];
  1686. } else {
  1687. NSString * stringURL = [NSString stringWithFormat:@"%@://%@%@%@%@/%@",
  1688. endpointURL.scheme,
  1689. host,
  1690. port,
  1691. path,
  1692. pathStylePath,
  1693. [OSSUtil encodeURL:objectKey]];
  1694. return [OSSTask taskWithResult:stringURL];
  1695. }
  1696. }];
  1697. }
  1698. @end
  1699. @implementation OSSClient (Utilities)
  1700. - (BOOL)doesObjectExistInBucket:(NSString *)bucketName
  1701. objectKey:(NSString *)objectKey
  1702. error:(const NSError **)error {
  1703. OSSHeadObjectRequest * headRequest = [OSSHeadObjectRequest new];
  1704. headRequest.bucketName = bucketName;
  1705. headRequest.objectKey = objectKey;
  1706. OSSTask * headTask = [self headObject:headRequest];
  1707. [headTask waitUntilFinished];
  1708. NSError *headError = headTask.error;
  1709. if (!headError) {
  1710. return YES;
  1711. } else {
  1712. if ([headError.domain isEqualToString: OSSServerErrorDomain] && labs(headError.code) == 404) {
  1713. return NO;
  1714. } else {
  1715. if (error != nil) {
  1716. *error = headError;
  1717. }
  1718. return NO;
  1719. }
  1720. }
  1721. }
  1722. @end
  1723. @implementation OSSClient (ImageService)
  1724. - (OSSTask *)imageActionPersist:(OSSImagePersistRequest *)request
  1725. {
  1726. if (![request.fromBucket oss_isNotEmpty]
  1727. || ![request.fromObject oss_isNotEmpty]
  1728. || ![request.toBucket oss_isNotEmpty]
  1729. || ![request.toObject oss_isNotEmpty]
  1730. || ![request.action oss_isNotEmpty]) {
  1731. NSError *error = [NSError errorWithDomain:OSSTaskErrorDomain
  1732. code:OSSClientErrorCodeInvalidArgument
  1733. userInfo:@{OSSErrorMessageTOKEN: @"imagePersist parameters not be empty!"}];
  1734. return [OSSTask taskWithError:error];
  1735. }
  1736. OSSNetworkingRequestDelegate *requestDelegate = request.requestDelegate;
  1737. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  1738. [params oss_setObject:@"" forKey:OSSHttpQueryProcess];
  1739. requestDelegate.uploadingData = [OSSUtil constructHttpBodyForImagePersist:request.action toBucket:request.toBucket toObjectKey:request.toObject];
  1740. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeImagePersist];
  1741. requestDelegate.responseParser = responseParser;
  1742. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  1743. neededMsg.endpoint = self.endpoint;
  1744. neededMsg.httpMethod = OSSHTTPMethodPOST;
  1745. neededMsg.bucketName = request.fromBucket;
  1746. neededMsg.objectKey = request.fromObject;
  1747. neededMsg.params = params;
  1748. requestDelegate.allNeededMessage = neededMsg;
  1749. requestDelegate.operType = OSSOperationTypeImagePersist;
  1750. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  1751. }
  1752. @end
  1753. @implementation OSSClient (Callback)
  1754. - (OSSTask *)triggerCallBack:(OSSCallBackRequest *)request
  1755. {
  1756. OSSNetworkingRequestDelegate *requestDelegate = request.requestDelegate;
  1757. NSMutableDictionary *params = [NSMutableDictionary dictionary];
  1758. [params oss_setObject:@"" forKey:OSSHttpQueryProcess];
  1759. NSString *paramString = [request.callbackParam base64JsonString];
  1760. NSString *variblesString = [request.callbackVar base64JsonString];
  1761. requestDelegate.uploadingData = [OSSUtil constructHttpBodyForTriggerCallback:paramString callbackVaribles:variblesString];
  1762. NSString *md5String = [OSSUtil base64Md5ForData:requestDelegate.uploadingData];
  1763. OSSHttpResponseParser *responseParser = [[OSSHttpResponseParser alloc] initForOperationType:OSSOperationTypeTriggerCallBack];
  1764. requestDelegate.responseParser = responseParser;
  1765. OSSAllRequestNeededMessage *neededMsg = [[OSSAllRequestNeededMessage alloc] init];
  1766. neededMsg.endpoint = self.endpoint;
  1767. neededMsg.httpMethod = OSSHTTPMethodPOST;
  1768. neededMsg.bucketName = request.bucketName;
  1769. neededMsg.objectKey = request.objectName;
  1770. neededMsg.contentMd5 = md5String;
  1771. neededMsg.params = params;
  1772. requestDelegate.allNeededMessage = neededMsg;
  1773. requestDelegate.operType = OSSOperationTypeTriggerCallBack;
  1774. return [self invokeRequest:requestDelegate requireAuthentication:request.isAuthenticationRequired];
  1775. }
  1776. @end