Skip to content

[firebase_storage] Implement "listAll" function #232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/firebase_storage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 3.1.0

* Update Android dependencies to latest.
* Implement `listAll` function both in Android and iOS.

## 3.0.6

* Update documentation to reflect new repository location.
Expand Down
6 changes: 3 additions & 3 deletions packages/firebase_storage/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ android {
disable 'InvalidPackage'
}
dependencies {
api 'com.google.firebase:firebase-storage:17.0.0'
implementation 'com.google.firebase:firebase-common:16.1.0'
implementation 'androidx.annotation:annotation:1.0.0'
api 'com.google.firebase:firebase-storage:19.1.0'
implementation 'com.google.firebase:firebase-common:19.1.0'
implementation 'androidx.annotation:annotation:1.1.0'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.google.firebase.FirebaseApp;
import com.google.firebase.storage.FileDownloadTask;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.ListResult;
import com.google.firebase.storage.OnPausedListener;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageException;
Expand Down Expand Up @@ -127,6 +128,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
case "UploadTask#cancel":
cancelUploadTask(call, result);
break;
case "StorageReference#listAll":
listAll(call, result);
break;
default:
result.notImplemented();
break;
Expand Down Expand Up @@ -285,6 +289,51 @@ private void putData(MethodCall call, Result result) {
result.success(handle);
}

private void listAll(MethodCall call, final Result result) {
String path = call.argument("path");
StorageReference ref = firebaseStorage.getReference().child(path);
final Task<ListResult> listTask = ref.listAll();
listTask.addOnSuccessListener(
new OnSuccessListener<ListResult>() {
@Override
public void onSuccess(ListResult listResult) {
Map<String, Object> map = new HashMap<>();
map.put("pageToken", listResult.getPageToken());
Map<String, Object> mapItems = new HashMap<>();
for (int i = 0; i < listResult.getItems().size(); i++) {
mapItems.put(
listResult.getItems().get(i).getName(),
buildMapStorageReference(listResult.getItems().get(i)));
}
map.put("items", mapItems);
Map<String, Object> mapPrefixes = new HashMap<>();
for (int i = 0; i < listResult.getPrefixes().size(); i++) {
mapPrefixes.put(
listResult.getPrefixes().get(i).getName(),
buildMapStorageReference(listResult.getPrefixes().get(i)));
}
map.put("prefixes", mapPrefixes);
result.success(map);
}
});
listTask.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
result.error("listing_error", e.getMessage(), null);
}
});
}

private Map<String, Object> buildMapStorageReference(StorageReference storageReference) {
Map<String, Object> map = new HashMap<>();
map.put("name", storageReference.getName());
map.put("bucket", storageReference.getBucket());
map.put("path", storageReference.getPath());
map.put("creationTimeMillis", storageReference.get)
return map;
}

private StorageMetadata buildMetadataFromMap(Map<String, Object> map) {
StorageMetadata.Builder builder = new StorageMetadata.Builder();
builder.setCacheControl((String) map.get("cacheControl"));
Expand Down Expand Up @@ -491,11 +540,9 @@ private Map<String, Object> ensureMimeType(Map<String, Object> metadata, Uri fil
if (metadata == null) {
metadata = new HashMap<>();
}

if (metadata.get("contentType") == null) {
metadata.put("contentType", getMimeType(file));
}

return metadata;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/firebase_storage/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ flutter {

dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

apply plugin: 'com.google.gms.google-services'
2 changes: 1 addition & 1 deletion packages/firebase_storage/example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {

dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.google.gms:google-services:4.3.0'
classpath 'com.google.gms:google-services:4.3.2'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
5C6F5A6F1EC3CCCC008D64B5 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
79B37B02170184518B1EE14B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
7A1ECC901E8EDB6900309407 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
Expand All @@ -58,6 +59,7 @@
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E13AAF33B0B411D7B2D38642 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E1D302E733C1AC2CD30777B6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -77,6 +79,8 @@
840012C8B5EDBCF56B0E4AC1 /* Pods */ = {
isa = PBXGroup;
children = (
79B37B02170184518B1EE14B /* Pods-Runner.debug.xcconfig */,
E1D302E733C1AC2CD30777B6 /* Pods-Runner.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
Expand Down Expand Up @@ -182,6 +186,7 @@
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 6934PS9FK8;
};
};
};
Expand All @@ -190,6 +195,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
Expand Down Expand Up @@ -241,16 +247,16 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
Expand Down Expand Up @@ -416,6 +422,7 @@
buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 6934PS9FK8;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -438,6 +445,7 @@
buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 6934PS9FK8;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@
<key>DATABASE_URL</key>
<string>https://flutter-firebase-plugins.firebaseio.com</string>
</dict>
</plist>
</plist>
6 changes: 3 additions & 3 deletions packages/firebase_storage/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ dependencies:
sdk: flutter
firebase_storage:
path: ../
firebase_core: ^0.4.0
uuid: ^1.0.0
http: ^0.12.0
firebase_core: ^0.4.0+9
uuid: ^2.0.2
http: ^0.12.0+2

dev_dependencies:
flutter_test:
Expand Down
35 changes: 35 additions & 0 deletions packages/firebase_storage/ios/Classes/FirebaseStoragePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
[self resumeUploadTask:call result:result];
} else if ([@"UploadTask#cancel" isEqualToString:call.method]) {
[self cancelUploadTask:call result:result];
} else if ([@"StorageReference#listAll" isEqualToString:call.method]) {
[self listAll:call result:result];
} else {
result(FlutterMethodNotImplemented);
}
Expand Down Expand Up @@ -407,6 +409,39 @@ - (void)getPath:(FlutterMethodCall *)call result:(FlutterResult)result {
result([ref fullPath]);
}

- (void)listAll:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *path = call.arguments[@"path"];
FIRStorageReference *ref = [storage.reference child:path];
[ref listAllWithCompletion:^(FIRStorageListResult *resultList, NSError *error) {
if (error != nil) {
result(getFlutterError(error));
} else {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:[resultList pageToken] forKey:@"pageToken"];
NSMutableDictionary *dictionaryItems = [[NSMutableDictionary alloc] init];
for (FIRStorageReference *item in resultList.items) {
[dictionaryItems setValue:[self buildDictionaryStorageReference:item] forKey:[item name]];
}
[dictionary setValue:dictionaryItems forKey:@"items"];
NSMutableDictionary *dictionaryPrefixes = [[NSMutableDictionary alloc] init];
for (FIRStorageReference *prefix in resultList.prefixes) {
[dictionaryPrefixes setValue:[self buildDictionaryStorageReference:prefix]
forKey:[prefix name]];
}
[dictionary setValue:dictionaryPrefixes forKey:@"prefixes"];
result(dictionary);
}
}];
}

- (NSDictionary *)buildDictionaryStorageReference:(FIRStorageReference *)storageReference {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:[storageReference name] forKey:@"name"];
[dictionary setValue:[storageReference bucket] forKey:@"bucket"];
[dictionary setValue:[storageReference fullPath] forKey:@"path"];
return dictionary;
}

- (void)getDownloadUrl:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *path = call.arguments[@"path"];
FIRStorageReference *ref = [storage.reference child:path];
Expand Down
3 changes: 3 additions & 0 deletions packages/firebase_storage/lib/firebase_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ part 'src/event.dart';
part 'src/firebase_storage.dart';
part 'src/storage_metadata.dart';
part 'src/storage_reference.dart';
part 'src/list_result.dart';
part 'src/list_result_item.dart';
part 'src/list_result_prefix.dart';
part 'src/upload_task.dart';
25 changes: 25 additions & 0 deletions packages/firebase_storage/lib/src/list_result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2017 The Chromium Authors & Daniel Szasz. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

part of firebase_storage;

/// Metadata for a [ListResult]. ListResult stores page token, items and
/// prefixes which are returned by list all results.

class ListResult {
ListResult({
this.pageToken,
this.items,
this.prefixes,
});

ListResult._fromMap(Map<String, dynamic> map)
: pageToken = map['pageToken'],
items = map['items'].cast<String, ListResultItem>(),
prefixes = map['prefixes'].cast<String, ListResultPrefix>();

final String pageToken;
final Map<String, ListResultItem> items;
final Map<String, ListResultPrefix> prefixes;
}
20 changes: 20 additions & 0 deletions packages/firebase_storage/lib/src/list_result_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 The Chromium Authors & Daniel Szasz. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

part of firebase_storage;

/// Metadata for a [ListResultItem]. ListResultItem stores name, bucket and
/// path.

class ListResultItem {
ListResultItem({
this.name,
this.bucket,
this.path,
});

final String name;
final String bucket;
final String path;
}
20 changes: 20 additions & 0 deletions packages/firebase_storage/lib/src/list_result_prefix.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 The Chromium Authors & Daniel Szasz. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

part of firebase_storage;

/// Metadata for a [ListResultPrefix]. ListResultPrefix stores name, bucket and
/// path.

class ListResultPrefix {
ListResultPrefix({
this.name,
this.bucket,
this.path,
});

final String name;
final String bucket;
final String path;
}
12 changes: 12 additions & 0 deletions packages/firebase_storage/lib/src/storage_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ class StorageReference {
return task;
}

/// Asynchronously retrieves the full list of all the items and prefixes
/// from a specific path. This is according to "listAll" in Android and
/// iOS Swift documentation.
Future<dynamic> listAll() async {
return await FirebaseStorage.channel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you're getting a complex data structure and returning it to the developer as a List<dynamic> that contains a bunch of Maps. Did you mean to call ListResult._fromMap()?

.invokeMethod<dynamic>("StorageReference#listAll", <String, String>{
'app': _firebaseStorage.app?.name,
'bucket': _firebaseStorage.storageBucket,
'path': _pathComponents.join("/"),
});
}

/// Asynchronously retrieves a long lived download URL with a revokable token.
/// This can be used to share the file with others, but can be revoked by a
/// developer in the Firebase Console if desired.
Expand Down
8 changes: 4 additions & 4 deletions packages/firebase_storage/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and
cost-effective object storage service for Android and iOS.
author: Flutter Team <[email protected]>
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_storage
version: 3.0.6
version: 3.1.0

flutter:
plugin:
Expand All @@ -14,13 +14,13 @@ flutter:
dependencies:
flutter:
sdk: flutter
firebase_core: ^0.4.0
firebase_core: ^0.4.0+9

dev_dependencies:
http: ^0.12.0
http: ^0.12.0+2
flutter_test:
sdk: flutter
uuid: "^1.0.0"
uuid: ^2.0.2
flutter_driver:
sdk: flutter
test: any
Expand Down
Empty file.
Empty file added res/values/strings_en.arb
Empty file.