はじめに
画像をFirebase Storageにアップロードし、
SDWebImageで取得しようとしたところ表示されず・・・。
解決するのに3時間くらいかかりました・・・。
同じような状態の方の参考になればなと思い、
備忘録がてら共有します!
環境
・Swift version 5.3
・XCode version 12.3
前提として
・Firebaseにアプリを登録していること
・CocoaPodsでFirebaseUIをインストールしていること
(Firebase/StorageやSDWebImageなど個別でも構いません)
コード
Storageに画像データを格納する際は、
UIImage型ではなくData型で格納しなければいけません。
なのでjpegData()
メソッドでData型に変換しています。
imageRef
は画像の格納先です。
child()
メソッドで子フォルダを作成します。
profileImageフォルダを作成しさらにその下に、"uid".jpgで保存しています。
次のコードがハマりポイント①の
meta.contentType = "image/jpeg"
です。
これは、画像のファイルタイプをapplication/octet-streamから
"image/jpeg"に変換しています。
これをしておかないとSDWebImageで画像を表示することができません。
その後は、imageRef.putData()
で画像をStorageに格納し、
imageRef.downloadURL()
の結果を
.setData(["imagePath" : "\(url)"])
でFirestoreに格納しています。
// 画像を.jpegData()メソッドでData型にする
let profileImage = icon.image!.jpegData(compressionQuality: 0.1)
// 格納先のパス
let imageRef = Storage.storage().reference().child("profileImage").child("\(uid!).jpg")
let meta = StorageMetadata()
// 画像データのタイプを変更する
meta.contentType = "image/jpeg"
imageRef.putData(profileImage!, metadata: meta) { (metaData, error) in
guard metaData != nil else {
print(error.debugDescription)
return
}
imageRef.downloadURL { (url, error) in
guard let url = url else {
return
}
// FirestoreにURL格納
self.db.collection("profileImage").document("\(self.uid!)").setData(["imagePath" : url.absoluteString])
}
}
ここまでで、Firebase Storageに画像データを送ることができました。
私の場合は次の画面で画像を取得して表示しているのでそのまま記載します。
先ほどFirestoreに格納した値をimagePathに格納します。
Firestoreからデータを取得する方法は、
getDocument()
メソッドを使用することで可能になります。
パスや値が存在した場合は、documentにデータが入るので、
document.get()
のようにget( )メソッドでデータの中の値を取得します。
icon.sd_setImage()
の箇所で画像を入れています。
(iconはUIImageView型です。)
var imagePath = ""
db.collection("profileImage").document("\(uid!)").getDocument { (document, error) in
guard let document = document else {
return
}
self.imagePath = document.get("imagePath") as! String
}
icon.sd_setImage(with: URL(string: imagePath), completed: nil)
ただ、これだけだと表示されない可能性があります。
というのも、Firebase Storageのセキュリティルールに引っ掛かり
データへのアクセスが拒否されている可能性があるからです。
こちらがハマりポイント②になります。
アクセス権限の変更方法は、FIrebaseのコンソールから行います。
Storage
-> Rules
-> ルールを編集 を選択します。
デフォルトだと下記のような状態かと思います。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
ここに/public
を追加します。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /public/{allPaths=**} { // この行に追加しました
allow read, write: if request.auth != null;
}
}
}
さいごに
publicを追加すると、公開フォルダ?的な感じになると思うので、
それだとセキュリティ的に不味い場合はやめた方がいいかもしれません。
おそらくですが、これでうまくいくと思います!
私の場合はこれで画像を取得することができました・・・。
冷静に考えれば分かることだったかもしれませんが、
なかなか気づかないものですね(笑)
以上、最後までご覧いただきありがとうございました。