[Flutter] - Firebase Storage 정리
Firebase에서도 미디어 파일을 관리하는 Colud Storage를 지원해준다.
Reference
reference는 file의 포인터이다.
firebase_storage.Reference ref =
firebase_storage.FirebaseStorage.instance.ref('/notes.txt');
2방식으로 사용가능하다.
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.ref('images/defaultProfile.png');
// or
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.ref()
.child('images')
.child('defaultProfile.png');
List files & directories
list와 listAll 함수를 통해 ListResult를 받아 올 수 있다.
Future<void> listExample() async {
firebase_storage.ListResult result =
await firebase_storage.FirebaseStorage.instance.ref().listAll();
result.items.forEach((firebase_storage.Reference ref) {
print('Found file: $ref');
});
result.prefixes.forEach((firebase_storage.Reference ref) {
print('Found directory: $ref');
});
}
listAll 함수는 모두 가져오기에 오랜 시간이 걸릴 수 있다. 그래서 list함수를 써보자
Future<void> listExample() async {
firebase_storage.ListResult result = await firebase_storage
.FirebaseStorage.instance
.ref()
.list(firebase_storage.ListOptions(maxResults: 10));
// ...
}
갯수 제한을 걸어 갯수 만큼만 받아오게 할 수 있다.
또한 reuslt에 있는 pageToken을 활용해 다음 페이지를 이어서 받아올 수 있다.
Future<void> listExample() async {
firebase_storage.ListResult result = await firebase_storage
.FirebaseStorage.instance
.ref()
.list(firebase_storage.ListOptions(maxResults: 10));
if (result.nextPageToken != null) {
firebase_storage.ListResult additionalResults = await firebase_storage
.FirebaseStorage.instance
.ref()
.list(firebase_storage.ListOptions(
maxResults: 10,
pageToken: result.nextPageToken,
));
}
}
Download URLs
Future<void> downloadURLExample() async {
String downloadURL = await firebase_storage.FirebaseStorage.instance
.ref('users/123/avatar.jpg')
.getDownloadURL();
// Within your widgets:
// Image.network(downloadURL);
}
Firebase CDN을 통해 확장가능하고 효율적이게 제공해준다.
Uploading Files
1. File uploads
파일업로드 이전에 가장 먼저 디바이스의 절대 경로를 생성해주어야 한다.
import 'package:path_provider/path_provider.dart';
Future<void> uploadExample() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
String filePath = '${appDocDir.absolute}/file-to-upload.png';
// ...
// e.g. await uploadFile(filePath);
}
그리고 File 객체를 putFile 함수를 통해 보내주자.
Future<void> uploadFile(String filePath) async {
File file = File(filePath);
try {
await firebase_storage.FirebaseStorage.instance
.ref('uploads/file-to-upload.png')
.putFile(file);
} on firebase_core.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
}
}
2. Upload from a String
putString 메서드를 사용하여 raw, base64, base64url 또는 data_url 인코딩 문자열을 업로드할 수 있다.
Future<void> uploadString() async {
String dataUrl = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==';
try {
await firebase_storage.FirebaseStorage.instance
.ref('uploads/hello-world.text')
.putString(dataUrl, format: firebase_storage.PutStringFormat.dataUrl);
} on firebase_core.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
}
}
3. Uploading raw data
Uint8List 타입의 데이터도 지원해준다.
import 'dart:convert' show utf8;
import 'dart:typed_data' show Uint8List;
Future<void> uploadData() async {
String text = 'Hello World!';
List<int> encoded = utf8.encode(text);
Uint8List data = Uint8List.fromList(encoded);
firebase_storage.Reference ref =
firebase_storage.FirebaseStorage.instance.ref('uploads/hello-world.text');
try {
// Upload raw data.
await ref.putData(data);
// Get raw data.
Uint8List downloadedData = await ref.getData();
// prints -> Hello World!
print(utf8.decode(downloadedData));
} on firebase_core.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
}
}
4. Adding Metadata
메타 데이터 추가 및 꺼내기 기능을 지원해준다.
Future<void> uploadFileWithMetadata(String filePath) async {
File file = File(filePath);
// Create your custom metadata.
firebase_storage.SettableMetadata metadata =
firebase_storage.SettableMetadata(
cacheControl: 'max-age=60',
customMetadata: <String, String>{
'userId': 'ABC123',
},
);
try {
// Pass metadata to any file upload method e.g putFile.
await firebase_storage.FirebaseStorage.instance
.ref('uploads/file-to-upload.png')
.putFile(file, metadata);
} on firebase_core.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
}
}
Future<void> getMetadataExample() async {
firebase_storage.FullMetadata metadata = await firebase_storage
.FirebaseStorage.instance
.ref('uploads/file-to-upload.png')
.getMetadata();
// As set in previous example.
print(metadata.customMetadata['userId']);
}
Downloading Files
로컬 디바이스에 저장하기 위해서는 writeToFile 함수를 사용하면 된다. 먼저 File 객체를 이용해 절대 경로를 설정해주자.
import 'package:path_provider/path_provider.dart';
Future<void> downloadFileExample() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
File downloadToFile = File('${appDocDir.path}/download-logo.png');
try {
await firebase_storage.FirebaseStorage.instance
.ref('uploads/logo.png')
.writeToFile(downloadToFile);
} on firebase_core.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
}
}
Handling Tasks
파일 업로드 혹은 다운로드는 UploadTask, DownloadTask를 리턴한다.
Task는 업로드,다운로드에서 상태 및 제어가 가능하다.
- TaskState.running : 현재 러닝 상태
- TaskState.paused : task 멈춰있는 상태
- TaskState.success : 완료된 상태
또한 아래처럼 pause, resume, cancle 함수를 사용 가능하다.
Future<void> handleTaskExample3(String filePath) async {
File largeFile = File(filePath);
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('uploads/hello-world.txt')
.putFile(largeFile);
// Pause the upload.
bool paused = await task.pause();
print('paused, $paused');
// Resume the upload.
bool resumed = await task.resume();
print('resumed, $resumed');
// Cancel the upload.
bool cancelled = await task.cancel();
print('cancelled, $cancelled');
// ...
}
cancle은 Exception으로 넘어가게 되니 유의하자.