FIRStorageReference.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. // Copyright 2017 Google
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "FIRStorageReference.h"
  15. #import "FIRStorageConstants_Private.h"
  16. #import "FIRStorageDeleteTask.h"
  17. #import "FIRStorageDownloadTask_Private.h"
  18. #import "FIRStorageGetMetadataTask.h"
  19. #import "FIRStorageMetadata_Private.h"
  20. #import "FIRStorageReference_Private.h"
  21. #import "FIRStorageTaskSnapshot.h"
  22. #import "FIRStorageTaskSnapshot_Private.h"
  23. #import "FIRStorageTask_Private.h"
  24. #import "FIRStorageUpdateMetadataTask.h"
  25. #import "FIRStorageUploadTask_Private.h"
  26. #import "FIRStorageUtils.h"
  27. #import "FIRStorage_Private.h"
  28. #import <FirebaseCore/FIRApp.h>
  29. #import <FirebaseCore/FIROptions.h>
  30. #import <GTMSessionFetcher/GTMSessionFetcher.h>
  31. #import "GTMSessionFetcherService.h"
  32. @implementation FIRStorageReference
  33. - (instancetype)init {
  34. FIRStorage *storage = [FIRStorage storage];
  35. NSString *storageBucket = storage.app.options.storageBucket;
  36. FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:storageBucket object:nil];
  37. FIRStorageReference *reference = [self initWithStorage:storage path:path];
  38. return reference;
  39. }
  40. - (instancetype)initWithStorage:(FIRStorage *)storage path:(FIRStoragePath *)path {
  41. self = [super init];
  42. if (self) {
  43. _storage = storage;
  44. _path = path;
  45. }
  46. return self;
  47. }
  48. #pragma mark - NSObject overrides
  49. - (instancetype)copyWithZone:(NSZone *)zone {
  50. FIRStorageReference *copiedReference =
  51. [[[self class] allocWithZone:zone] initWithStorage:_storage path:_path];
  52. return copiedReference;
  53. }
  54. - (BOOL)isEqual:(id)object {
  55. if (self == object) {
  56. return YES;
  57. }
  58. if (![object isKindOfClass:[FIRStorageReference class]]) {
  59. return NO;
  60. }
  61. BOOL isObjectEqual = [self isEqualToFIRStorageReference:(FIRStorageReference *)object];
  62. return isObjectEqual;
  63. }
  64. - (BOOL)isEqualToFIRStorageReference:(FIRStorageReference *)reference {
  65. BOOL isEqual = [_storage isEqual:reference.storage] && [_path isEqual:reference.path];
  66. return isEqual;
  67. }
  68. - (NSUInteger)hash {
  69. NSUInteger hash = [_storage hash] ^ [_path hash];
  70. return hash;
  71. }
  72. - (NSString *)description {
  73. return [self stringValue];
  74. }
  75. - (NSString *)stringValue {
  76. NSString *value = [NSString stringWithFormat:@"gs://%@/%@", _path.bucket, _path.object ?: @""];
  77. return value;
  78. }
  79. #pragma mark - Property Getters
  80. - (NSString *)bucket {
  81. NSString *bucket = _path.bucket;
  82. return bucket;
  83. }
  84. - (NSString *)fullPath {
  85. NSString *path = _path.object;
  86. if (!path) {
  87. path = @"";
  88. }
  89. return path;
  90. }
  91. - (NSString *)name {
  92. NSString *name = [_path.object lastPathComponent];
  93. if (!name) {
  94. name = @"";
  95. }
  96. return name;
  97. }
  98. #pragma mark - Path Operations
  99. - (FIRStorageReference *)root {
  100. FIRStoragePath *rootPath = [_path root];
  101. FIRStorageReference *rootReference =
  102. [[FIRStorageReference alloc] initWithStorage:_storage path:rootPath];
  103. return rootReference;
  104. }
  105. - (nullable FIRStorageReference *)parent {
  106. FIRStoragePath *parentPath = [_path parent];
  107. if (!parentPath) {
  108. return nil;
  109. }
  110. FIRStorageReference *parentReference =
  111. [[FIRStorageReference alloc] initWithStorage:_storage path:parentPath];
  112. return parentReference;
  113. }
  114. - (FIRStorageReference *)child:(NSString *)path {
  115. FIRStoragePath *childPath = [_path child:path];
  116. FIRStorageReference *childReference =
  117. [[FIRStorageReference alloc] initWithStorage:_storage path:childPath];
  118. return childReference;
  119. }
  120. #pragma mark - Uploads
  121. - (FIRStorageUploadTask *)putData:(NSData *)uploadData {
  122. return [self putData:uploadData metadata:nil completion:nil];
  123. }
  124. - (FIRStorageUploadTask *)putData:(NSData *)uploadData
  125. metadata:(nullable FIRStorageMetadata *)metadata {
  126. return [self putData:uploadData metadata:metadata completion:nil];
  127. }
  128. - (FIRStorageUploadTask *)putData:(NSData *)uploadData
  129. metadata:(nullable FIRStorageMetadata *)metadata
  130. completion:(nullable FIRStorageVoidMetadataError)completion {
  131. if (!metadata) {
  132. metadata = [[FIRStorageMetadata alloc] init];
  133. }
  134. metadata.path = _path.object;
  135. metadata.name = [_path.object lastPathComponent];
  136. FIRStorageUploadTask *task =
  137. [[FIRStorageUploadTask alloc] initWithReference:self
  138. fetcherService:_storage.fetcherServiceForApp
  139. data:uploadData
  140. metadata:metadata];
  141. if (completion) {
  142. dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
  143. if (!callbackQueue) {
  144. callbackQueue = dispatch_get_main_queue();
  145. }
  146. [task observeStatus:FIRStorageTaskStatusSuccess
  147. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  148. dispatch_async(callbackQueue, ^{
  149. completion(snapshot.metadata, nil);
  150. });
  151. }];
  152. [task observeStatus:FIRStorageTaskStatusFailure
  153. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  154. dispatch_async(callbackQueue, ^{
  155. completion(nil, snapshot.error);
  156. });
  157. }];
  158. }
  159. [task enqueue];
  160. return task;
  161. }
  162. - (FIRStorageUploadTask *)putFile:(NSURL *)fileURL {
  163. return [self putFile:fileURL metadata:nil completion:nil];
  164. }
  165. - (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
  166. metadata:(nullable FIRStorageMetadata *)metadata {
  167. return [self putFile:fileURL metadata:metadata completion:nil];
  168. }
  169. - (FIRStorageUploadTask *)putFile:(NSURL *)fileURL
  170. metadata:(nullable FIRStorageMetadata *)metadata
  171. completion:(nullable FIRStorageVoidMetadataError)completion {
  172. if (!metadata) {
  173. metadata = [[FIRStorageMetadata alloc] init];
  174. }
  175. metadata.path = _path.object;
  176. metadata.name = [_path.object lastPathComponent];
  177. FIRStorageUploadTask *task =
  178. [[FIRStorageUploadTask alloc] initWithReference:self
  179. fetcherService:_storage.fetcherServiceForApp
  180. file:fileURL
  181. metadata:metadata];
  182. if (completion) {
  183. dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
  184. if (!callbackQueue) {
  185. callbackQueue = dispatch_get_main_queue();
  186. }
  187. [task observeStatus:FIRStorageTaskStatusSuccess
  188. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  189. dispatch_async(callbackQueue, ^{
  190. completion(snapshot.metadata, nil);
  191. });
  192. }];
  193. [task observeStatus:FIRStorageTaskStatusFailure
  194. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  195. dispatch_async(callbackQueue, ^{
  196. completion(nil, snapshot.error);
  197. });
  198. }];
  199. }
  200. [task enqueue];
  201. return task;
  202. }
  203. #pragma mark - Downloads
  204. - (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size
  205. completion:(FIRStorageVoidDataError)completion {
  206. FIRStorageDownloadTask *task =
  207. [[FIRStorageDownloadTask alloc] initWithReference:self
  208. fetcherService:_storage.fetcherServiceForApp
  209. file:nil];
  210. dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
  211. if (!callbackQueue) {
  212. callbackQueue = dispatch_get_main_queue();
  213. }
  214. [task observeStatus:FIRStorageTaskStatusSuccess
  215. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  216. FIRStorageDownloadTask *task = snapshot.task;
  217. dispatch_async(callbackQueue, ^{
  218. completion(task.downloadData, nil);
  219. });
  220. }];
  221. [task observeStatus:FIRStorageTaskStatusFailure
  222. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  223. dispatch_async(callbackQueue, ^{
  224. completion(nil, snapshot.error);
  225. });
  226. }];
  227. [task
  228. observeStatus:FIRStorageTaskStatusProgress
  229. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  230. FIRStorageDownloadTask *task = snapshot.task;
  231. if (task.progress.totalUnitCount > size || task.progress.completedUnitCount > size) {
  232. NSDictionary *infoDictionary = @{
  233. @"totalSize" : @(task.progress.totalUnitCount),
  234. @"maxAllowedSize" : @(size)
  235. };
  236. NSError *error =
  237. [FIRStorageErrors errorWithCode:FIRStorageErrorCodeDownloadSizeExceeded
  238. infoDictionary:infoDictionary];
  239. [task cancelWithError:error];
  240. }
  241. }];
  242. [task enqueue];
  243. return task;
  244. }
  245. - (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL {
  246. return [self writeToFile:fileURL completion:nil];
  247. }
  248. - (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL
  249. completion:(FIRStorageVoidURLError)completion {
  250. FIRStorageDownloadTask *task =
  251. [[FIRStorageDownloadTask alloc] initWithReference:self
  252. fetcherService:_storage.fetcherServiceForApp
  253. file:fileURL];
  254. if (completion) {
  255. dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
  256. if (!callbackQueue) {
  257. callbackQueue = dispatch_get_main_queue();
  258. }
  259. [task observeStatus:FIRStorageTaskStatusSuccess
  260. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  261. dispatch_async(callbackQueue, ^{
  262. completion(fileURL, nil);
  263. });
  264. }];
  265. [task observeStatus:FIRStorageTaskStatusFailure
  266. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  267. dispatch_async(callbackQueue, ^{
  268. completion(nil, snapshot.error);
  269. });
  270. }];
  271. }
  272. [task enqueue];
  273. return task;
  274. }
  275. - (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion {
  276. dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
  277. if (!callbackQueue) {
  278. callbackQueue = dispatch_get_main_queue();
  279. }
  280. return [self metadataWithCompletion:^(FIRStorageMetadata *metadata, NSError *error) {
  281. dispatch_async(callbackQueue, ^{
  282. completion(metadata.downloadURL, error);
  283. });
  284. }];
  285. }
  286. #pragma mark - Metadata Operations
  287. - (void)metadataWithCompletion:(FIRStorageVoidMetadataError)completion {
  288. FIRStorageGetMetadataTask *task =
  289. [[FIRStorageGetMetadataTask alloc] initWithReference:self
  290. fetcherService:_storage.fetcherServiceForApp
  291. completion:completion];
  292. [task enqueue];
  293. }
  294. - (void)updateMetadata:(FIRStorageMetadata *)metadata
  295. completion:(nullable FIRStorageVoidMetadataError)completion {
  296. FIRStorageUpdateMetadataTask *task =
  297. [[FIRStorageUpdateMetadataTask alloc] initWithReference:self
  298. fetcherService:_storage.fetcherServiceForApp
  299. metadata:metadata
  300. completion:completion];
  301. [task enqueue];
  302. }
  303. #pragma mark - Delete
  304. - (void)deleteWithCompletion:(nullable FIRStorageVoidError)completion {
  305. FIRStorageDeleteTask *task =
  306. [[FIRStorageDeleteTask alloc] initWithReference:self
  307. fetcherService:_storage.fetcherServiceForApp
  308. completion:completion];
  309. [task enqueue];
  310. }
  311. @end