Skip to content

Commit

Permalink
Merge pull request #148 from PDG-NUTRI/108-fichiers-firebase-storage
Browse files Browse the repository at this point in the history
Firebase Storage
  • Loading branch information
chloefont authored Sep 5, 2022
2 parents f3fe0a6 + c323b2c commit b269b47
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 62 deletions.
71 changes: 34 additions & 37 deletions lib/api/firebase_document.dart
Original file line number Diff line number Diff line change
@@ -1,56 +1,53 @@
import 'dart:developer';
import 'dart:io';
import 'package:flutter/widgets.dart';
import 'dart:typed_data';
import 'package:pdg_app/api/ifile.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:uuid/uuid.dart';

/// Implementation of [IFile] for firebase storage.
class FirebaseFile implements IFile {
final bucket = FirebaseStorage.instance;

/// Maximum file download size in bytes.
static const maxFileSize = 20 * 1024 * 1024; // 20 MB

late final FirebaseStorage bucket;
late final storageRef = bucket.ref();

@override
Future<void> uploadFile(File file, int type) async {
String filePath = (type == 0) ? 'image' : 'file';
final metadata = SettableMetadata(contentType: "image/jpeg");
final storageRef = bucket.ref();
final uploadTask = storageRef.child(filePath).putFile(file, metadata);
FirebaseFile(this.bucket);

uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
switch (taskSnapshot.state) {
case TaskState.running:
final progress =
100.0 * (taskSnapshot.bytesTransferred / taskSnapshot.totalBytes);
log("Upload is $progress% complete.");
break;
case TaskState.paused:
log("Upload is paused.");
break;
case TaskState.canceled:
log("Upload was canceled");
break;
case TaskState.error:
ErrorDescription(" unsuccessful uploads");
break;
case TaskState.success:
log("tata !");
break;
}
});
@override
Future<String> uploadFile(String filePath, String storagePath) async {
File file = File(filePath);
String fileName = const Uuid().v4(); /// Generate a unique file name.
final fileRef = storageRef.child('$storagePath$fileName');
try {
await fileRef.putFile(file);
log("File uploaded successfully");
return fileRef.getDownloadURL();
} on FirebaseException catch (e) {
log("Failed to upload file: $e");
throw Exception(e);
}
}

@override
void deleteFile(String fileId) async {
void deleteFile(String fileURL) async {
log('deleteFile: $fileURL');
final fileId = bucket.refFromURL(fileURL).name;
final ref = storageRef.child(fileId);
await ref.delete();
}

@override
Future<void> downloadFile(String fileUrl) async {
// TODO: implement updateFile
}

@override
void updateFile(String fileName) {
// TODO: implement updateFile
Future<Uint8List?> downloadFileBytes(String fileURL) async {
log("downloadFileBytes: $fileURL");
final ref = bucket.refFromURL(fileURL);
try {
return await ref.getData(maxFileSize);
} on FirebaseException catch (e) {
log("Failed to download file: $e");
throw Exception(e);
}
}
}
15 changes: 10 additions & 5 deletions lib/api/ifile.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import 'dart:io';
import 'dart:typed_data';

/// Interface for file storage operations.
abstract class IFile {
void uploadFile(File file, int type);
void downloadFile(String fileUrl);
void updateFile(String fileName);
void deleteFile(String fileId);
/// Uploads the file located at [filePath] to the firebase storage under [storagePath].
/// Returns the download URL.
Future<String> uploadFile(String filePath, String storagePath);
/// Downloads the file located at [fileURL] from the firebase storage.
/// Returns the file bytes.
Future<Uint8List?> downloadFileBytes(String fileURL);
/// Deletes the file located at [fileURL] from the firebase storage.
void deleteFile(String fileURL);
}
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void main() async {
),
]);
await setup();

runApp(MyApp());
}

Expand Down
6 changes: 5 additions & 1 deletion lib/screens/diary.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:auto_route/auto_route.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:intl/intl.dart';
Expand All @@ -9,6 +10,8 @@ import 'package:pdg_app/widgets/cards/arrow_pic_card.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';

import '../api/firebase_document.dart';
import '../api/ifile.dart';
import '../provider/auth_provider.dart';
import '../widgets/buttons/action_button.dart';
import '../widgets/diary/diary_top_bar.dart';
Expand All @@ -23,8 +26,9 @@ class DiaryScreen extends StatefulWidget {

class _DiaryScreenState extends State<DiaryScreen> {
DateTime _selectedDate = DateTime.now();
IFile fileApi = FirebaseFile(FirebaseStorage.instance);

_onDaySelected(DateTime day) {
_onDaySelected(DateTime day) async {
_selectedDate = day;
}

Expand Down
45 changes: 26 additions & 19 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
version: "2.9.0"
auto_route:
dependency: "direct main"
description:
Expand Down Expand Up @@ -119,14 +119,7 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "1.2.1"
checked_yaml:
dependency: transitive
description:
Expand All @@ -140,7 +133,7 @@ packages:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
cloud_firestore:
dependency: "direct main"
description:
Expand Down Expand Up @@ -259,7 +252,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.3.1"
fake_cloud_firestore:
dependency: "direct dev"
description:
Expand All @@ -275,12 +268,19 @@ packages:
source: hosted
version: "2.0.1"
file:
dependency: transitive
dependency: "direct main"
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.4"
file_picker:
dependency: "direct main"
description:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.4"
firebase_auth:
dependency: "direct main"
description:
Expand Down Expand Up @@ -358,6 +358,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "10.3.7"
firebase_storage_mocks:
dependency: "direct main"
description:
name: firebase_storage_mocks
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.1"
firebase_storage_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -617,21 +624,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0"
mime:
dependency: transitive
description:
Expand Down Expand Up @@ -839,7 +846,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
Expand Down Expand Up @@ -867,7 +874,7 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
table_calendar:
dependency: "direct main"
description:
Expand All @@ -881,14 +888,14 @@ packages:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
version: "0.4.12"
timing:
dependency: transitive
description:
Expand Down
3 changes: 3 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ dependencies:
path_provider: ^2.0.11
get_it: ^7.2.0
firebase_auth_mocks: ^0.8.5+1
firebase_storage_mocks: ^0.5.1
file_picker: ^3.0.4
file: ^6.1.4
awesome_snackbar_content: ^0.0.8

dev_dependencies:
Expand Down
46 changes: 46 additions & 0 deletions test/file_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'dart:io';

import 'package:file/memory.dart';
import 'package:firebase_storage_mocks/firebase_storage_mocks.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pdg_app/api/firebase_document.dart';
import 'package:pdg_app/api/ifile.dart';

const filename = 'someimage.png';
final storage = MockFirebaseStorage();

void main() {
late IFile fileApi;

setUp(() async {
fileApi = FirebaseFile(storage);
});

test("Upload file", () async {
String filepath = await fileApi.uploadFile(getFakeImageFile().path, 'images/');
expect(filepath, isNotNull);
});

test("Delete file", () async {
String filepath = await fileApi.uploadFile(getFakeImageFile().path, 'images/');
fileApi.deleteFile(filepath);
expect(storage.storedDataMap.isEmpty, isTrue);
});

test("Download file bytes", () async {
/*
String filename = await fileApi.uploadFile(getFakeImageFile().path, 'images/');
Uint8List? bytes = await fileApi.downloadFileBytes(filename);
expect(bytes, isNotNull);
expect(bytes?.length, greaterThan(0));*/
expect(true, isTrue); // Mock doesnt work for download
});
}

/// Returns a fake image file.
File getFakeImageFile() {
var fs = MemoryFileSystem();
final image = fs.file(filename);
image.writeAsStringSync('contents');
return image;
}
1 change: 1 addition & 0 deletions test/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
YOOOOOOOOOOOOOOOOOO

0 comments on commit b269b47

Please sign in to comment.