Firebase 的檔案存取(storage)

Firebase 提供空間給我們儲存檔案,比方圖片,影片等,讓我們可以寫程式上傳和下載檔案。

進入 Firebase 的專案頁面,點選 Build 下的 Storage

點選 Get started

點選 Start in test mode。

檔案存取權限

預設要登入的使用者才能存取,它的 Storage Security Rules 如下。

service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}

公開的 Storage Security Rules 如下,它將讓任何人都能存取檔案。

service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}

一開始測試練習時,可先改成方便測試的公開權限,之後有需要再加入權限控制。

修改 Storage Security Rules 的步驟說明

  1. 切換到 Storage 的 Rules 分頁。

2. 修改 Storage Security Rules,點選 Publish 完成修改。

由於我們將權限設為較危險的公開,因此上方會顯示紅色警告。

利用 SPM 加入 Firebase 套件的 FirebaseStorage

import FirebaseStorage

使用 Firebase 的檔案存取功能,必須先 import FirebaseStorage。

import FirebaseStorage

上傳檔案

定義 function uploadPhoto。

func uploadPhoto(image: UIImage, completion: @escaping (Result<URL, Error>) -> Void) {

let fileReference = Storage.storage().reference().child(UUID().uuidString + ".jpg")
if let data = image.jpegData(compressionQuality: 0.9) {

fileReference.putData(data, metadata: nil) { result in
switch result {
case .success:
fileReference.downloadURL(completion: completion)
case .failure(let error):
completion(.failure(error))
}
}
}
}

呼叫 function。

let uiImage = UIImage(named: "peter")
uploadPhoto(image: uiImage!) { result in
switch result {
case .success(let url):
print(url)
case .failure(let error):
print(error)
}
}

成功上傳到 Firebase Storage 的檔案將可從 Storage 的 Files 頁面查詢。

上傳檔案 & 將檔案設成使用者的個人頭像

  • 方法 1: 利用 function uploadPhoto 上傳照片,然後將網址存入 FireStore 資料庫 User 的 photoURL。(ps: 假設 User 有個欄位是 photoURL)
let uiImage = UIImage(named: "peter")
uploadPhoto(image: uiImage!) { result in
switch result {
case .success(let url):
// save url in FireStore User's photoURL
case .failure(let error):
print(error)
}
}
  • 方法 2: 利用 function uploadPhoto 上傳照片,然後將網址存入 Firebase User 的 photoURL。
func setUserPhoto(url: URL) {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.photoURL = url
changeRequest?.commitChanges(completion: { error in
guard error == nil else {
print(error?.localizedDescription)
return
}
})
}
let uiImage = UIImage(named: "peter")
uploadPhoto(image: uiImage!) { result in
switch result {
case .success(let url):
setUserPhoto(url: url)
case .failure(let error):
print(error)
}
}

下載檔案

分成以下兩種方法。

方法1: 透過檔案的網址抓取

將檔案的網址存在 Firestore 資料庫裡,然後讀取 Firestore 資料庫後,從網址抓取檔案。

方法2: 利用 StorageReference 的 getData 抓資料

假設我們想抓取下圖的 peter.png。

Button(action: {
let fileReference = Storage.storage().reference().child("pic/cute/peter.png")
fileReference.getData(maxSize: 10 * 1024 * 1024) { result in
switch result {
case .success(let data):
print(data)
case .failure(let error):
print(error)
}
}
}, label: {
Text("Button")
})

檔案的路徑為 pic/cute/peter.png,參數 maxSize 設定抓取的最大檔案 size 為 10 MB。

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com