[ios] FirebaseStorageの使い方・Singleを使って実装する。

現在、firebaseのstorageを使ってProfile画像を作っています。

主な使い方は、Firebaseのドキュメントを使って知ることができます。

Cloud Storage  |  Firebase

はじめに

CocoaPodsでFirebase/Storageをインストールします。

use_frameworks!
pod "Firebase"
pod "Firebase/Storage"

次にFirebase Storageの設定を修正します。 今はAuthorizeしたユーザーしかファイルの読み書きをできないので、誰でもできるように変更します。

FirebaseはStorageは、Pathを Storage.storage().reference() にchildを使って指定します。 child("a").child("b") と書くとaの中のbに画像が保存されます。

今回は、UserProfileを保存したいので、pathは .child("users").child("profile") とします。

let ref = Storage.storage().reference().child("users").child("profile") と変数を持たせれば、画像の取得を楽にすることができます。

画像のアップロード

画像のアップロードは、setDataと言う関数を用いることで使用することができます。 setDataの引数には、保存したい画像のData型とmetaDataを渡します。 metadataは、以下のURLで確認してください。

https://firebase.google.com/docs/storage/ios/file-metadata?hl=ja

基本は、nilで大丈夫です。

以下で、UIImageからData型に直すことができます。 0.3と言う数字は、画質に関する情報なのですが、容量の重い画像だとアップロードに時間がかかるので比較的小さい数字でいい気がします。 let imageData = myProfile.jpegData(compressionQuality: 0.3)

戻り値は、metadataとerrorが帰ってくるので、ハンドリングすれば終わりです。

つい数ヶ月前までは、metadata?.downloadURL()で保存先のURLを取得できたのですが現在は使えないようです。

以下がアップロードの処理です。

 func uploadUserProfile(imageData: Data) -> Single<Void> {
        let ref = Storage.storage().reference().child("users").child("profile")
        return Single.create { observer in
            ref.putData(imageData, metadata: nil) { metadata, error in
                if let error = error {
                    observer(.error(error))
                    return
                }
                observer(.success(()))
            }
            return Disposables.create()
        }
    }

画像のダウンロード

ダウンロードには、Data型とURLで取得する2通りの取得方法があります。

Data型で取得する。

Data型は、getDataで取得することができます。引数に、画像のサイズ ' maxSize 'を書きます。 ドキュメントには、1 * 1024 * 1024と書いてありました。 そして、引数には dataerror が帰ってきます。

 func downloadUserProfile() -> Single<Data> {
        let ref = Storage.storage().reference().child("users").child("profile")
        return Single.create { observer in
            ref.getData(maxSize: 1 * 1024 * 1024, completion: { data, error in
                if let error = error {
                    observer(.error(error))
                    return
                }
                guard let data = data else {
                    fatalError()
                }
                observer(.success(data))
            })
            return Disposables.create()
        }
    }

URL型で取得する

現在のプロダクトは、Kingfisherで画像をキャッシュしているのでURLで取得しています。 URLかたで受け取るには、downloadURLで取得でき、引数は必要ありません。 引数には URLerror が帰ってきます。

 func downloadProfileURL() -> Single<URL> {
        let ref = Storage.storage().reference().child("users").child("profile")
        return Single.create { observer in
            ref.downloadURL(completion: { url, error in
                if let error = error {
                    observer(.error(error))
                    return
                }
                guard let url = url else {
                    fatalError()
                }
                observer(.success(url))
            })
            return Disposables.create()
        }
    }

Singleを使うと、流れてくる最初の値のみを流しsuucessとerro rを流すため、APIなど 成功したら結果を、失敗したらエラー情報を返す場合 に便利に使えます。