Result.swift 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright 2020 Google LLC
  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 FirebaseStorage
  15. private enum DataError: Error {
  16. case internalInconsistency // Thrown when both value and error are nil.
  17. }
  18. /// Generates a closure that returns a `Result` type from a closure that returns an optional type
  19. /// and `Error`.
  20. ///
  21. /// - Parameters:
  22. /// - completion: A completion block returning a `Result` enum with either a generic object or
  23. /// an `Error`.
  24. /// - Returns: A closure parameterized with an optional generic and optional `Error` to match
  25. /// Objective C APIs.
  26. private func getResultCallback<T>(completion: @escaping (Result<T, Error>) -> Void) -> (_: T?,
  27. _: Error?)
  28. -> Void {
  29. return { (value: T?, error: Error?) -> Void in
  30. if let value = value {
  31. completion(.success(value))
  32. } else if let error = error {
  33. completion(.failure(error))
  34. } else {
  35. completion(.failure(DataError.internalInconsistency))
  36. }
  37. }
  38. }
  39. public extension StorageReference {
  40. /// Asynchronously retrieves a long lived download URL with a revokable token.
  41. /// This can be used to share the file with others, but can be revoked by a developer
  42. /// in the Firebase Console.
  43. ///
  44. /// - Parameters:
  45. /// - completion: A completion block returning a `Result` enum with either a URL or an `Error`.
  46. func downloadURL(completion: @escaping (Result<URL, Error>) -> Void) {
  47. downloadURL(completion: getResultCallback(completion: completion))
  48. }
  49. /// Asynchronously downloads the object at the `StorageReference` to a `Data` object.
  50. /// A `Data` of the provided max size will be allocated, so ensure that the device has enough
  51. /// memory to complete. For downloading large files, the `write` API may be a better option.
  52. /// - Parameters:
  53. /// - maxSize: The maximum size in bytes to download.
  54. /// - completion: A completion block returning a `Result` enum with either a `Data` object or
  55. /// an `Error`.
  56. ///
  57. /// - Returns: A StorageDownloadTask that can be used to monitor or manage the download.
  58. @discardableResult
  59. func getData(maxSize: Int64, completion: @escaping (Result<Data, Error>) -> Void)
  60. -> StorageDownloadTask {
  61. return getData(maxSize: maxSize, completion: getResultCallback(completion: completion))
  62. }
  63. /// Retrieves metadata associated with an object at the current path.
  64. ///
  65. /// - Parameters:
  66. /// - completion: A completion block which returns a `Result` enum with either the
  67. /// object metadata or an `Error`.
  68. func getMetadata(completion: @escaping (Result<StorageMetadata, Error>) -> Void) {
  69. getMetadata(completion: getResultCallback(completion: completion))
  70. }
  71. /// Resumes a previous `list` call, starting after a pagination token.
  72. /// Returns the next set of items (files) and prefixes (folders) under this StorageReference.
  73. ///
  74. /// "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
  75. /// paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
  76. /// filtered.
  77. ///
  78. /// Only available for projects using Firebase Rules Version 2.
  79. ///
  80. /// - Parameters:
  81. /// - maxResults The maximum number of results to return in a single page. Must be
  82. /// greater than 0 and at most 1000.
  83. /// - pageToken A page token from a previous call to list.
  84. /// - completion A completion handler that will be invoked with the next items and
  85. /// prefixes under the current StorageReference. It returns a `Result` enum
  86. /// with either the list or an `Error`.
  87. func list(maxResults: Int64,
  88. pageToken: String,
  89. completion: @escaping (Result<StorageListResult, Error>) -> Void) {
  90. list(maxResults: maxResults,
  91. pageToken: pageToken,
  92. completion: getResultCallback(completion: completion))
  93. }
  94. /// List up to `maxResults` items (files) and prefixes (folders) under this StorageReference.
  95. ///
  96. /// "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
  97. /// paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
  98. /// filtered.
  99. ///
  100. /// Only available for projects using Firebase Rules Version 2.
  101. ///
  102. /// - Parameters:
  103. /// - maxResults The maximum number of results to return in a single page. Must be
  104. /// greater than 0 and at most 1000.
  105. /// - completion A completion handler that will be invoked with the next items and
  106. /// prefixes under the current `StorageReference`. It returns a `Result` enum
  107. /// with either the list or an `Error`.
  108. func list(maxResults: Int64,
  109. completion: @escaping (Result<StorageListResult, Error>) -> Void) {
  110. list(maxResults: maxResults,
  111. completion: getResultCallback(completion: completion))
  112. }
  113. /// List all items (files) and prefixes (folders) under this StorageReference.
  114. ///
  115. /// This is a helper method for calling list() repeatedly until there are no more results.
  116. /// Consistency of the result is not guaranteed if objects are inserted or removed while this
  117. /// operation is executing. All results are buffered in memory.
  118. ///
  119. /// Only available for projects using Firebase Rules Version 2.
  120. ///
  121. /// - Parameters:
  122. /// - completion A completion handler that will be invoked with all items and prefixes
  123. /// under the current StorageReference. It returns a `Result` enum with either the
  124. /// list or an `Error`.
  125. func listAll(completion: @escaping (Result<StorageListResult, Error>) -> Void) {
  126. listAll(completion: getResultCallback(completion: completion))
  127. }
  128. /// Asynchronously uploads data to the currently specified `StorageReference`.
  129. /// This is not recommended for large files, and one should instead upload a file from disk.
  130. ///
  131. /// - Parameters:
  132. /// - uploadData The `Data` to upload.
  133. /// - metadata `StorageMetadata` containing additional information (MIME type, etc.)
  134. /// about the object being uploaded.
  135. /// - completion A completion block that returns a `Result` enum with either the
  136. /// object metadata or an `Error`.
  137. ///
  138. /// - Returns: An instance of `StorageUploadTask`, which can be used to monitor or manage
  139. /// the upload.
  140. @discardableResult
  141. func putData(_ uploadData: Data,
  142. metadata: StorageMetadata? = nil,
  143. completion: @escaping (Result<StorageMetadata, Error>) -> Void)
  144. -> StorageUploadTask {
  145. return putData(uploadData,
  146. metadata: metadata,
  147. completion: getResultCallback(completion: completion))
  148. }
  149. /// Asynchronously uploads a file to the currently specified `StorageReference`.
  150. ///
  151. /// - Parameters:
  152. /// - from A URL representing the system file path of the object to be uploaded.
  153. /// - metadata `StorageMetadata` containing additional information (MIME type, etc.)
  154. /// about the object being uploaded.
  155. /// - completion A completion block that returns a `Result` enum with either the
  156. /// object metadata or an `Error`.
  157. ///
  158. /// - Returns: An instance of `StorageUploadTask`, which can be used to monitor or manage
  159. /// the upload.
  160. @discardableResult
  161. func putFile(from: URL,
  162. metadata: StorageMetadata? = nil,
  163. completion: @escaping (Result<StorageMetadata, Error>) -> Void)
  164. -> StorageUploadTask {
  165. return putFile(from: from,
  166. metadata: metadata,
  167. completion: getResultCallback(completion: completion))
  168. }
  169. /// Updates the metadata associated with an object at the current path.
  170. ///
  171. /// - Parameters:
  172. /// - metadata A `StorageMetadata` object with the metadata to update.
  173. /// - completion A completion block which returns a `Result` enum with either the
  174. /// object metadata or an `Error`.
  175. func updateMetadata(_ metadata: StorageMetadata,
  176. completion: @escaping (Result<StorageMetadata, Error>) -> Void) {
  177. updateMetadata(metadata, completion: getResultCallback(completion: completion))
  178. }
  179. /// Asynchronously downloads the object at the current path to a specified system filepath.
  180. ///
  181. /// - Parameters:
  182. /// - toFile A file system URL representing the path the object should be downloaded to.
  183. /// - completion A completion block that fires when the file download completes. The
  184. /// block returns a `Result` enum with either an NSURL pointing to the file
  185. /// path of the downloaded file or an `Error`.
  186. ///
  187. /// - Returns: A `StorageDownloadTask` that can be used to monitor or manage the download.
  188. @discardableResult
  189. func write(toFile: URL, completion: @escaping (Result<URL, Error>)
  190. -> Void) -> StorageDownloadTask {
  191. return write(toFile: toFile, completion: getResultCallback(completion: completion))
  192. }
  193. }