| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- // Copyright 2022 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- import Foundation
- import FirebaseStorageObjC
- /**
- * StorageReference represents a reference to a Google Cloud Storage object. Developers can
- * upload and download objects, as well as get/set object metadata, and delete an object at the
- * path.
- * @see https://cloud.google.com/storage/
- */
- @objc(FIRStorageReference) open class StorageReference: NSObject {
- // MARK: - Public APIs
- /**
- * The Storage service object which created this reference.
- */
- @objc public let storage: Storage
- /**
- * The name of the Google Cloud Storage bucket associated with this reference,
- * in gs://bucket/path/to/object.txt, the bucket would be: 'bucket'
- */
- @objc public let bucket: String
- /**
- * The full path to this object, not including the Google Cloud Storage bucket.
- * In gs://bucket/path/to/object.txt, the full path would be: 'path/to/object.txt'
- */
- @objc public let fullPath: String
- /**
- * The short name of the object associated with this reference,
- * in gs://bucket/path/to/object.txt, the name of the object would be: 'object.txt'
- */
- @objc public let name: String
- /**
- * Creates a new StorageReference pointing to the root object.
- * @return A new StorageReference pointing to the root object.
- */
- @objc open func root() -> StorageReference {
- return StorageReference(impl: impl.root(), storage: storage)
- }
- /**
- * Creates a new StorageReference pointing to the parent of the current reference
- * or nil if this instance references the root location.
- * For example:
- * path = foo/bar/baz parent = foo/bar
- * path = foo parent = (root)
- * path = (root) parent = nil
- * @return A new StorageReference pointing to the parent of the current reference.
- */
- @objc open func parent() -> StorageReference? {
- guard let parent = impl.parent() else {
- return nil
- }
- return StorageReference(impl: parent, storage: storage)
- }
- /**
- * Creates a new StorageReference pointing to a child object of the current reference.
- * path = foo child = bar newPath = foo/bar
- * path = foo/bar child = baz ntask.impl.snapshotwPath = foo/bar/baz
- * All leading and trailing slashes will be removed, and consecutive slashes will be
- * compressed to single slashes. For example:
- * child = /foo/bar newPath = foo/bar
- * child = foo/bar/ newPath = foo/bar
- * child = foo///bar newPath = foo/bar
- * @param path Path to append to the current path.
- * @return A new StorageReference pointing to a child location of the current reference.
- */
- @objc(child:) open func child(_ path: String) -> StorageReference {
- return StorageReference(impl: impl.child(path), storage: storage)
- }
- // MARK: - Uploads
- /**
- * Asynchronously uploads data to the currently specified StorageReference,
- * without additional metadata.
- * This is not recommended for large files, and one should instead upload a file from disk.
- * @param uploadData The Data to upload.
- * @param metadata StorageMetadata containing additional information (MIME type, etc.)
- * about the object being uploaded.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putData:metadata:)
- @discardableResult
- open func putData(_ uploadData: Data, metadata: StorageMetadata? = nil) -> StorageUploadTask {
- return StorageUploadTask(impl.put(uploadData, metadata: metadata?.impl))
- }
- /**
- * Asynchronously uploads data to the currently specified StorageReference.
- * This is not recommended for large files, and one should instead upload a file from disk.
- * @param uploadData The Data to upload.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putData:) @discardableResult open func __putData(_ uploadData: Data) -> StorageUploadTask {
- return StorageUploadTask(impl.put(uploadData))
- }
- /**
- * Asynchronously uploads data to the currently specified StorageReference.
- * This is not recommended for large files, and one should instead upload a file from disk.
- * @param uploadData The Data to upload.
- * @param metadata StorageMetadata containing additional information (MIME type, etc.)
- * about the object being uploaded.
- * @param completion A completion block that either returns the object metadata on success,
- * or an error on failure.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putData:metadata:completion:) @discardableResult
- open func putData(_ uploadData: Data,
- metadata: StorageMetadata? = nil,
- completion: ((_: StorageMetadata?, _: Error?) -> Void)?) -> StorageUploadTask {
- return StorageUploadTask(impl.put(uploadData, metadata: metadata?.impl) { impl, error in
- if let completion = completion {
- self.adaptMetadataCallback(completion: completion)(impl, error)
- }
- })
- }
- /**
- * Asynchronously uploads a file to the currently specified StorageReference.
- * @param fileURL A URL representing the system file path of the object to be uploaded.
- * @param metadata StorageMetadata containing additional information (MIME type, etc.)
- * about the object being uploaded.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putFile:metadata:) @discardableResult
- open func putFile(from fileURL: URL, metadata: StorageMetadata? = nil) -> StorageUploadTask {
- return StorageUploadTask(impl.putFile(fileURL, metadata: metadata?.impl))
- }
- /**
- * Asynchronously uploads a file to the currently specified StorageReference,
- * without additional metadata.
- * @param fileURL A URL representing the system file path of the object to be uploaded.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putFile:) @discardableResult open func __putFile(from fileURL: URL) -> StorageUploadTask {
- return StorageUploadTask(impl.putFile(fileURL))
- }
- /**
- * Asynchronously uploads a file to the currently specified StorageReference.
- * @param fileURL A URL representing the system file path of the object to be uploaded.
- * @param metadata StorageMetadata containing additional information (MIME type, etc.)
- * about the object being uploaded.
- * @param completion A completion block that either returns the object metadata on success,
- * or an error on failure.
- * @return An instance of StorageUploadTask, which can be used to monitor or manage the upload.
- */
- @objc(putFile:metadata:completion:) @discardableResult
- open func putFile(from fileURL: URL,
- metadata: StorageMetadata? = nil,
- completion: ((_: StorageMetadata?, _: Error?) -> Void)?) -> StorageUploadTask {
- return StorageUploadTask(impl.putFile(fileURL, metadata: metadata?.impl) { impl, error in
- if let completion = completion {
- self.adaptMetadataCallback(completion: completion)(impl, error)
- }
- })
- }
- // MARK: - Downloads
- /**
- * Asynchronously downloads the object at the StorageReference to an Data object in memory.
- * An Data of the provided max size will be allocated, so ensure that the device has enough free
- * memory to complete the download. For downloading large files, writeToFile may be a better option.
- * @param maxSize The maximum size in bytes to download. If the download exceeds this size,
- * the task will be cancelled and an error will be returned.
- * @param completion A completion block that either returns the object data on success,
- * or an error on failure.
- * @return An StorageDownloadTask that can be used to monitor or manage the download.
- */
- @objc(dataWithMaxSize:completion:) @discardableResult
- open func getData(maxSize: Int64,
- completion: @escaping ((_: Data?, _: Error?) -> Void)) -> StorageDownloadTask {
- return StorageDownloadTask(impl.data(withMaxSize: maxSize, completion: completion))
- }
- /**
- * Asynchronously retrieves a long lived download URL with a revokable token.
- * This can be used to share the file with others, but can be revoked by a developer
- * in the Firebase Console.
- * @param completion A completion block that either returns the URL on success,
- * or an error on failure.
- */
- @objc(downloadURLWithCompletion:)
- open func downloadURL(completion: @escaping ((_: URL?, _: Error?) -> Void)) {
- impl.downloadURL(completion: completion)
- }
- #if compiler(>=5.5) && canImport(_Concurrency)
- @available(iOS 13, tvOS 13, macOS 10.15, watchOS 8, *)
- /**
- * Asynchronously retrieves a long lived download URL with a revokable token.
- * This can be used to share the file with others, but can be revoked by a developer
- * in the Firebase Console.
- * @returns completion The URL on success.
- */
- open func downloadURL() async throws -> URL {
- return try await impl.downloadURL()
- }
- #endif // compiler(>=5.5) && canImport(_Concurrency)
- /**
- * Asynchronously downloads the object at the current path to a specified system filepath.
- * @param fileURL A file system URL representing the path the object should be downloaded to.
- * @return An StorageDownloadTask that can be used to monitor or manage the download.
- */
- @objc(writeToFile:) @discardableResult
- open func write(toFile fileURL: URL) -> StorageDownloadTask {
- return StorageDownloadTask(impl.write(toFile: fileURL))
- }
- /**
- * Asynchronously downloads the object at the current path to a specified system filepath.
- * @param fileURL A file system URL representing the path the object should be downloaded to.
- * @param completion A completion block that fires when the file download completes.
- * Returns an URL pointing to the file path of the downloaded file on success,
- * or an error on failure.
- * @return An StorageDownloadTask that can be used to monitor or manage the download.
- */
- @objc(writeToFile:completion:) @discardableResult
- open func write(toFile fileURL: URL,
- completion: ((_: URL?, _: Error?) -> Void)?) -> StorageDownloadTask {
- return StorageDownloadTask(impl.write(toFile: fileURL, completion: completion))
- }
- // MARK: - List Support
- /**
- * List all items (files) and prefixes (folders) under this StorageReference.
- *
- * This is a helper method for calling list() repeatedly until there are no more results.
- * Consistency of the result is not guaranteed if objects are inserted or removed while this
- * operation is executing. All results are buffered in memory.
- *
- * `listAll(completion:)` is only available for projects using Firebase Rules Version 2.
- *
- * @param completion A completion handler that will be invoked with all items and prefixes under
- * the current StorageReference.
- */
- @objc(listAllWithCompletion:)
- open func listAll(completion: @escaping ((_: StorageListResult?, _: Error?) -> Void)) {
- impl.listAll { listResult, error in
- if error != nil {
- completion(nil, error)
- } else {
- completion(StorageListResult(listResult), error)
- }
- }
- }
- #if compiler(>=5.5) && canImport(_Concurrency)
- @available(iOS 13, tvOS 13, macOS 10.15, watchOS 8, *)
- /**
- * List all items (files) and prefixes (folders) under this StorageReference.
- *
- * This is a helper method for calling list() repeatedly until there are no more results.
- * Consistency of the result is not guaranteed if objects are inserted or removed while this
- * operation is executing. All results are buffered in memory.
- *
- * `listAll()` is only available for projects using Firebase Rules Version 2.
- *
- * @returns completion All items and prefixes under the current StorageReference.
- */
- open func listAll() async throws -> StorageListResult {
- return try await StorageListResult(impl.listAll())
- }
- #endif // compiler(>=5.5) && canImport(_Concurrency)
- /**
- * List up to `maxResults` items (files) and prefixes (folders) under this StorageReference.
- *
- * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
- * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
- * filtered.
- *
- * `list(maxResults:completion:)` is only available for projects using Firebase Rules Version 2.
- *
- * @param maxResults The maximum number of results to return in a single page. Must be greater
- * than 0 and at most 1000.
- * @param completion A completion handler that will be invoked with up to maxResults items and
- * prefixes under the current StorageReference.
- */
- @objc(listWithMaxResults:completion:)
- open func list(maxResults: Int64,
- completion: @escaping ((_: StorageListResult?, _: Error?) -> Void)) {
- impl.list(withMaxResults: maxResults) { listResult, error in
- if error != nil {
- completion(nil, error)
- } else {
- completion(StorageListResult(listResult), error)
- }
- }
- }
- /**
- * Resumes a previous call to list(maxResults:completion:)`, starting after a pagination token.
- * Returns the next set of items (files) and prefixes (folders) under this StorageReference.
- *
- * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object
- * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be
- * filtered.
- *
- * `list(maxResults:pageToken:completion:)`is only available for projects using Firebase Rules
- * Version 2.
- *
- * @param maxResults The maximum number of results to return in a single page. Must be greater
- * than 0 and at most 1000.
- * @param pageToken A page token from a previous call to list.
- * @param completion A completion handler that will be invoked with the next items and prefixes
- * under the current StorageReference.
- */
- @objc(listWithMaxResults:pageToken:completion:)
- open func list(maxResults: Int64,
- pageToken: String,
- completion: @escaping ((_: StorageListResult?, _: Error?) -> Void)) {
- impl.list(withMaxResults: maxResults, pageToken: pageToken) { listResult, error in
- if error != nil {
- completion(nil, error)
- } else {
- completion(StorageListResult(listResult), error)
- }
- }
- }
- // MARK: - Metadata Operations
- /**
- * Retrieves metadata associated with an object at the current path.
- * @param completion A completion block which returns the object metadata on success,
- * or an error on failure.
- */
- @objc(metadataWithCompletion:)
- open func getMetadata(completion: @escaping ((_: StorageMetadata?, _: Error?) -> Void)) {
- impl.metadata { impl, error in
- self.adaptMetadataCallback(completion: completion)(impl, error)
- }
- }
- #if compiler(>=5.5) && canImport(_Concurrency)
- @available(iOS 13, tvOS 13, macOS 10.15, watchOS 8, *)
- /**
- * Retrieves metadata associated with an object at the current path.
- * @returns The object metadata on success.
- */
- open func getMetadata() async throws -> StorageMetadata {
- return try await StorageMetadata(impl: impl.metadata())
- }
- #endif // compiler(>=5.5) && canImport(_Concurrency)
- /**
- * Updates the metadata associated with an object at the current path.
- * @param metadata An StorageMetadata object with the metadata to update.
- * @param completion A completion block which returns the StorageMetadata on success,
- * or an error on failure.
- */
- @objc(updateMetadata:completion:)
- open func updateMetadata(_ metadata: StorageMetadata,
- completion: ((_: StorageMetadata?, _: Error?) -> Void)?) {
- impl.update(metadata.impl) { impl, error in
- if let completion = completion {
- self.adaptMetadataCallback(completion: completion)(impl, error)
- }
- }
- }
- #if compiler(>=5.5) && canImport(_Concurrency)
- @available(iOS 13, tvOS 13, macOS 10.15, watchOS 8, *)
- /**
- * Updates the metadata associated with an object at the current path.
- * @param metadata An StorageMetadata object with the metadata to update.
- * @returns The object metadata on success.
- */
- open func updateMetadata(_ metadata: StorageMetadata) async throws -> StorageMetadata {
- return try await StorageMetadata(impl: impl.update(metadata.impl))
- }
- #endif // compiler(>=5.5) && canImport(_Concurrency)
- private func adaptMetadataCallback(completion: @escaping (StorageMetadata?, Error?) -> Void) ->
- (_: FIRIMPLStorageMetadata?, _: Error?)
- -> Void {
- return { (impl: FIRIMPLStorageMetadata?, error: Error?) in
- if let impl = impl {
- completion(StorageMetadata(impl: impl), error)
- } else {
- completion(nil, error)
- }
- }
- }
- // MARK: - Delete
- /**
- * Deletes the object at the current path.
- * @param completion A completion block which returns nil on success, or an error on failure.
- */
- @objc(deleteWithCompletion:)
- open func delete(completion: ((_: Error?) -> Void)?) {
- impl.delete(completion: completion)
- }
- #if compiler(>=5.5) && canImport(_Concurrency)
- @available(iOS 13, tvOS 13, macOS 10.15, watchOS 8, *)
- /**
- * Deletes the object at the current path.
- */
- open func delete() async throws {
- return try await impl.delete()
- }
- #endif // compiler(>=5.5) && canImport(_Concurrency)
- // MARK: - NSObject overrides
- @objc open func copy(_ zone: NSZone) -> StorageReference {
- return StorageReference(impl.copy() as! FIRIMPLStorageReference)
- }
- @objc override open func isEqual(_ object: Any?) -> Bool {
- guard let ref = object as? StorageReference else {
- return false
- }
- return impl.isEqual(ref.impl)
- }
- @objc override public var hash: Int {
- return impl.hash
- }
- @objc override public var description: String {
- return impl.description
- }
- // MARK: - Internal APIs
- private let impl: FIRIMPLStorageReference
- internal convenience init(_ impl: FIRIMPLStorageReference) {
- self.init(impl: impl, storage: Storage(app: impl.storage.app, bucket: impl.bucket))
- }
- internal init(impl: FIRIMPLStorageReference, storage: Storage) {
- self.impl = impl
- self.storage = storage
- bucket = impl.bucket
- fullPath = impl.fullPath
- name = impl.name
- }
- }
|