import 'dart:io'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'api_exceptions.dart'; abstract class FirebaseStorageClient { Future<String> uploadFile(String path, String filePath); Future<void> downloadFile(String path, String downloadToPath); Future<void> deleteFile(String path); Future<String> getFileUrl(String path); } class FirebaseStorageClientImpl extends FirebaseStorageClient { final FirebaseStorage _storage; FirebaseStorageClientImpl(this._storage); @override Future<String> uploadFile(String path, String filePath) async { try { final ref = _storage.ref().child(path); final uploadTask = ref.putFile(File(filePath)); await uploadTask.whenComplete(() {}); return await ref.getDownloadURL(); } catch (e) { throw _handleError(e, tr('errorUploadingFile')); } } @override Future<void> downloadFile(String path, String downloadToPath) async { try { final ref = _storage.ref().child(path); final file = File(downloadToPath); await ref.writeToFile(file); } catch (e) { throw _handleError(e, tr('errorDownloadingFile')); } } @override Future<void> deleteFile(String path) async { try { final ref = _storage.ref().child(path); await ref.delete(); } catch (e) { throw _handleError(e, tr('errorDeletingFile')); } } @override Future<String> getFileUrl(String path) async { try { final ref = _storage.ref().child(path); return await ref.getDownloadURL(); } catch (e) { throw _handleError(e, tr('errorGettingFileUrl')); } } Exception _handleError(dynamic error, String defaultMessage) { if (error is FirebaseException) { switch (error.code) { case 'permission-denied': return UnauthorisedException(); case 'not-found': return Exception(defaultMessage); default: return ExceptionWithMessage('$defaultMessage: ${error.message}'); } } return Exception(defaultMessage); } }