Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Add support for updateMetadata #503

Merged
merged 3 commits into from
Apr 23, 2018
Merged
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
4 changes: 4 additions & 0 deletions packages/firebase_storage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.2.6

* Added support for updateMetadata.

## 0.2.5

* Added StorageMetadata class, support for getMetadata, and support for uploading file with metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void onMethodCall(MethodCall call, final Result result) {
case "StorageReference#getMetadata":
getMetadata(call, result);
break;
case "StorageReference#updateMetadata":
updateMetadata(call, result);
break;
default:
result.notImplemented();
break;
Expand All @@ -70,22 +73,28 @@ private void getMetadata(MethodCall call, final Result result) {
new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(StorageMetadata storageMetadata) {
Map<String, Object> map = new HashMap<>();
map.put("name", storageMetadata.getName());
map.put("bucket", storageMetadata.getBucket());
map.put("generation", storageMetadata.getGeneration());
map.put("metadataGeneration", storageMetadata.getMetadataGeneration());
map.put("path", storageMetadata.getPath());
map.put("sizeBytes", storageMetadata.getSizeBytes());
map.put("creationTimeMillis", storageMetadata.getCreationTimeMillis());
map.put("updatedTimeMillis", storageMetadata.getUpdatedTimeMillis());
map.put("md5Hash", storageMetadata.getMd5Hash());
map.put("cacheControl", storageMetadata.getCacheControl());
map.put("contentDisposition", storageMetadata.getContentDisposition());
map.put("contentEncoding", storageMetadata.getContentEncoding());
map.put("contentLanguage", storageMetadata.getContentLanguage());
map.put("contentType", storageMetadata.getContentType());
result.success(map);
result.success(buildMapFromMetadata(storageMetadata));
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
result.error("metadata_error", e.getMessage(), null);
}
});
}

private void updateMetadata(MethodCall call, final Result result) {
String path = call.argument("path");
Map<String, Object> metadata = call.argument("metadata");
StorageReference ref = firebaseStorage.getReference().child(path);
ref.updateMetadata(buildMetadataFromMap(metadata))
.addOnSuccessListener(
new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(StorageMetadata storageMetadata) {
result.success(buildMapFromMetadata(storageMetadata));
}
})
.addOnFailureListener(
Expand Down Expand Up @@ -175,6 +184,25 @@ private StorageMetadata buildMetadataFromMap(Map<String, Object> map) {
return builder.build();
}

private Map<String, Object> buildMapFromMetadata(StorageMetadata storageMetadata) {
Map<String, Object> map = new HashMap<>();
map.put("name", storageMetadata.getName());
map.put("bucket", storageMetadata.getBucket());
map.put("generation", storageMetadata.getGeneration());
map.put("metadataGeneration", storageMetadata.getMetadataGeneration());
map.put("path", storageMetadata.getPath());
map.put("sizeBytes", storageMetadata.getSizeBytes());
map.put("creationTimeMillis", storageMetadata.getCreationTimeMillis());
map.put("updatedTimeMillis", storageMetadata.getUpdatedTimeMillis());
map.put("md5Hash", storageMetadata.getMd5Hash());
map.put("cacheControl", storageMetadata.getCacheControl());
map.put("contentDisposition", storageMetadata.getContentDisposition());
map.put("contentEncoding", storageMetadata.getContentEncoding());
map.put("contentLanguage", storageMetadata.getContentLanguage());
map.put("contentType", storageMetadata.getContentType());
return map;
}

private void getData(MethodCall call, final Result result) {
Integer maxSize = call.argument("maxSize");
String path = call.argument("path");
Expand Down
60 changes: 40 additions & 20 deletions packages/firebase_storage/ios/Classes/FirebaseStoragePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
[self delete:call result:result];
} else if ([@"StorageReference#getMetadata" isEqualToString:call.method]) {
[self getMetadata:call result:result];
} else if ([@"StorageReference#updateMetadata" isEqualToString:call.method]) {
[self updateMetadata:call result:result];
} else {
result(FlutterMethodNotImplemented);
}
Expand Down Expand Up @@ -93,6 +95,29 @@ - (FIRStorageMetadata *)buildMetadataFromDictionary:(NSDictionary *)dictionary {
return metadata;
}

- (NSDictionary *)buildDictionaryFromMetadata:(FIRStorageMetadata *)metadata {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:[metadata bucket] forKey:@"bucket"];
[dictionary setValue:[NSString stringWithFormat:@"%lld", [metadata generation]]
forKey:@"generation"];
[dictionary setValue:[NSString stringWithFormat:@"%lld", [metadata metageneration]]
forKey:@"metadataGeneration"];
[dictionary setValue:[metadata path] forKey:@"path"];
[dictionary setValue:@((long)([[metadata timeCreated] timeIntervalSince1970] * 1000.0))
forKey:@"creationTimeMillis"];
[dictionary setValue:@((long)([[metadata updated] timeIntervalSince1970] * 1000.0))
forKey:@"updatedTimeMillis"];
[dictionary setValue:@([metadata size]) forKey:@"sizeBytes"];
[dictionary setValue:[metadata md5Hash] forKey:@"md5Hash"];
[dictionary setValue:[metadata cacheControl] forKey:@"cacheControl"];
[dictionary setValue:[metadata contentDisposition] forKey:@"contentDisposition"];
[dictionary setValue:[metadata contentEncoding] forKey:@"contentEncoding"];
[dictionary setValue:[metadata contentLanguage] forKey:@"contentLanguage"];
[dictionary setValue:[metadata contentType] forKey:@"contentType"];
[dictionary setValue:[metadata name] forKey:@"name"];
return dictionary;
}

- (void)getData:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *maxSize = call.arguments[@"maxSize"];
NSString *path = call.arguments[@"path"];
Expand Down Expand Up @@ -121,30 +146,25 @@ - (void)getMetadata:(FlutterMethodCall *)call result:(FlutterResult)result {
if (error != nil) {
result(error.flutterError);
} else {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:[metadata bucket] forKey:@"bucket"];
[dictionary setValue:[NSString stringWithFormat:@"%lld", [metadata generation]]
forKey:@"generation"];
[dictionary setValue:[NSString stringWithFormat:@"%lld", [metadata metageneration]]
forKey:@"metadataGeneration"];
[dictionary setValue:[metadata path] forKey:@"path"];
[dictionary setValue:@((long)([[metadata timeCreated] timeIntervalSince1970] * 1000.0))
forKey:@"creationTimeMillis"];
[dictionary setValue:@((long)([[metadata updated] timeIntervalSince1970] * 1000.0))
forKey:@"updatedTimeMillis"];
[dictionary setValue:@([metadata size]) forKey:@"sizeBytes"];
[dictionary setValue:[metadata md5Hash] forKey:@"md5Hash"];
[dictionary setValue:[metadata cacheControl] forKey:@"cacheControl"];
[dictionary setValue:[metadata contentDisposition] forKey:@"contentDisposition"];
[dictionary setValue:[metadata contentEncoding] forKey:@"contentEncoding"];
[dictionary setValue:[metadata contentLanguage] forKey:@"contentLanguage"];
[dictionary setValue:[metadata contentType] forKey:@"contentType"];
[dictionary setValue:[metadata name] forKey:@"name"];
result(dictionary);
result([self buildDictionaryFromMetadata:metadata]);
}
}];
}

- (void)updateMetadata:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *path = call.arguments[@"path"];
NSDictionary *metadataDictionary = call.arguments[@"metadata"];
FIRStorageReference *ref = [[FIRStorage storage].reference child:path];
[ref updateMetadata:[self buildMetadataFromDictionary:metadataDictionary]
completion:^(FIRStorageMetadata *metadata, NSError *error) {
if (error != nil) {
result(error.flutterError);
} else {
result([self buildDictionaryFromMetadata:metadata]);
}
}];
}

- (void)getDownloadUrl:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *path = call.arguments[@"path"];
FIRStorageReference *ref = [[FIRStorage storage].reference child:path];
Expand Down
33 changes: 24 additions & 9 deletions packages/firebase_storage/lib/firebase_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ class StorageReference {
}));
}

/// Updates the metadata associated with this [StorageReference].
Copy link
Contributor

Choose a reason for hiding this comment

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

Please document what the method returns.

///
/// Returns a [Future] that will complete to the updated [StorageMetadata].
///
/// This method ignores fields of [metadata] that cannot be set by the public
/// [StorageMetadata] constructor. Writable metadata properties can be deleted
/// by passing the empty string.
Future<StorageMetadata> updateMetadata(StorageMetadata metadata) async {
return new StorageMetadata._fromMap(await FirebaseStorage.channel
.invokeMethod("StorageReference#updateMetadata", <String, dynamic>{
'path': _pathComponents.join("/"),
'metadata': metadata == null ? null : _buildMetadataUploadMap(metadata),
}));
}

String get path => _pathComponents.join('/');
}

Expand Down Expand Up @@ -174,16 +189,16 @@ class StorageUploadTask {
_completer
.complete(new UploadTaskSnapshot(downloadUrl: Uri.parse(downloadUrl)));
}
}

Map<String, dynamic> _buildMetadataUploadMap(StorageMetadata metadata) {
return <String, dynamic>{
'cacheControl': metadata.cacheControl,
'contentDisposition': metadata.contentDisposition,
'contentLanguage': metadata.contentLanguage,
'contentType': metadata.contentType,
'contentEncoding': metadata.contentEncoding,
};
}
Map<String, dynamic> _buildMetadataUploadMap(StorageMetadata metadata) {
return <String, dynamic>{
'cacheControl': metadata.cacheControl,
'contentDisposition': metadata.contentDisposition,
'contentLanguage': metadata.contentLanguage,
'contentType': metadata.contentType,
'contentEncoding': metadata.contentEncoding,
};
}

class UploadTaskSnapshot {
Expand Down
2 changes: 1 addition & 1 deletion 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 <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_storage
version: 0.2.5
version: 0.2.6

flutter:
plugin:
Expand Down
62 changes: 62 additions & 0 deletions packages/firebase_storage/test/firebase_storage_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,68 @@ void main() {
});
});

group('updateMetadata', () {
final List<MethodCall> log = <MethodCall>[];

StorageReference ref;

setUp(() {
FirebaseStorage.channel
.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
switch (methodCall.method) {
case 'StorageReference#getMetadata':
return <String, String>{
'name': 'image.jpg',
};
break;
case 'StorageReference#updateMetadata':
return <String, String>{
'name': 'image.jpg',
'contentLanguage': 'en'
};
break;
default:
break;
}
});
ref = FirebaseStorage.instance
.ref()
.child('avatars')
.child('large')
.child('image.jpg');
});

test('invokes correct method', () async {
await ref.updateMetadata(const StorageMetadata(contentLanguage: 'en'));

expect(log, <Matcher>[
isMethodCall(
'StorageReference#updateMetadata',
arguments: <String, dynamic>{
'path': 'avatars/large/image.jpg',
'metadata': <String, String>{
'cacheControl': null,
'contentDisposition': null,
'contentLanguage': 'en',
'contentType': null,
'contentEncoding': null
},
},
),
]);
});

test('returns correct result', () async {
expect((await ref.getMetadata()).contentLanguage, null);
expect(
(await ref.updateMetadata(
const StorageMetadata(contentLanguage: 'en')))
.contentLanguage,
'en');
});
});

group('getDownloadUrl', () {
final List<MethodCall> log = <MethodCall>[];

Expand Down