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

Commit

Permalink
Add support for updateMetadata (#503)
Browse files Browse the repository at this point in the history
  • Loading branch information
szakarias authored Apr 23, 2018
1 parent ec3b007 commit 93d1c24
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 46 deletions.
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].
///
/// 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

0 comments on commit 93d1c24

Please sign in to comment.