Firebase Storage的功能和Google Drive分享檔案連結很像,只要你有檔案的連結就可以進行讀取的行為,它的好處是能夠結合Authentication來對存取者的身分做限制。
設定好伺服器位置後會看到以下的畫面,把畫底線的url記下來,待會會使用到。
Firebase Storage不像Firestore要設定集合和文件,當然你也可以像設定資料夾一樣把檔案做分類,在這為了方便就略過這個步驟。
如此一來我們就設定好Storage了。
可惜事情沒這麼簡單,我原本以為上傳到Storage的檔案可以單純的用固定的網址加上檔名或是能像資料庫一樣用過濾的方式取得我要的檔案,不料這些在Storage都行不通,要存取每個檔案除了網址外還需要有一個token
參數才行,而Storage也沒有提供類似where
或search
的功能可以使用。
舉個存取檔案網址的例子:https://firebasestorage.googleapis.com/v0/b/fluttube-97b64.appspot.com/o/abc123%40123.455.jpg?alt=media&token=01f46d33-1a7b-4415-94de-10ace7b98ff4 ,可以看見後頭需要額外的token參數才能讀取檔案而每個檔案的token都是不同的。
想了許多替代方案,最後決定在Firestore,多增加一個「Users」的集合,當使用者上傳圖片後就取得圖片的下載網址儲存下來。
之後就能直接用使用者的信箱去找到對應的圖片網址,再用Image.network(url)
顯示圖片。
備註:後來發現可以透過設定讀取規則,讓Read不受限制,設定好後不需token也可存取到檔案。
但考慮到安全性還是決定採用上面的方式,絕對不是實作完才發現還有這招(x)。
為了讓每個使用者只會有一筆「文件」紀錄,所以就用使用者信箱當作文件ID,每次上傳新的圖片就更新圖片網址。
在pubspec.yaml,加上以下兩個Package引用。
回到專案,在firebase資料夾下,新增「upload_storage.dart」。
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart' as p;
import 'dart:io';
StorageUploadTask uploadImage(File image, String email) {
final extension = p.extension(image.path);
final StorageReference ref =
FirebaseStorage(storageBucket: 'your_storage_Bucket')
.ref()
.child('$email$extension');
StorageUploadTask uploadTask = ref.putFile(image);
return uploadTask;
}
上傳的程式碼只有短短4行:
第一行 取出Local端圖片的副檔名
第二行 根據你的Bucket Url並設定上傳後的檔名(這邊就用信箱加上副檔名,也可以隨機產生亂數)
第三行 把本地端的圖片上傳到剛剛設定好的reference上。
最後回傳UploadTask,可以用來查看上傳狀態。
開啟firebase/firestore_database.dart。
多增加兩個function用來查詢和更新使用者的圖片路徑。
Future<String> getProfilePictureUrl(String email) async {
// 用使用者信箱當作索引值去找到對應的文件
var doc = await Firestore.instance.collection('Users').document(email).get();
if (doc.exists) {
return doc.data['profile_picture_url'];
}
return '';
}
void updateProfilePictureUrl(String email, String url) async {
// 用使用者信箱當作索引值去新增or更新 圖片路徑
await Firestore.instance.collection("Users").document(email).setData({
'profile_picture_url': url,
});
}
今天花了很多時間思考要怎麼把圖片網址和使用者做連接比較好,結果因為經驗太淺選擇用了不是很聰明的方式,額外用一個資料表來做對照,所以上傳圖片和在留言版顯示大頭貼的功能就明天再來做了。
完整程式碼在這裡-> FlutTube Github