Skip to content

Commit

Permalink
Updated dowload file options to accept bucket parameter
Browse files Browse the repository at this point in the history
added integration tests
  • Loading branch information
ekjotmultani committed Nov 6, 2024
1 parent 1b43cc4 commit c23fc64
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:aws_common/aws_common.dart';
import 'package:amplify_core/amplify_core.dart';

/// {@template amplify_core.storage.download_file_options}
/// Configurable options for `Amplify.Storage.downloadFile`.
Expand All @@ -14,20 +14,25 @@ class StorageDownloadFileOptions
/// {@macro amplify_core.storage.download_file_options}
const StorageDownloadFileOptions({
this.pluginOptions,
this.bucket,
});

/// {@macro amplify_core.storage.download_file_plugin_options}
final StorageDownloadFilePluginOptions? pluginOptions;

/// Optionally specify which bucket to target
final StorageBucket? bucket;

@override
List<Object?> get props => [pluginOptions];
List<Object?> get props => [pluginOptions, bucket];

@override
String get runtimeTypeName => 'StorageDownloadFileOptions';

@override
Map<String, Object?> toJson() => {
'pluginOptions': pluginOptions?.toJson(),
'bucket': bucket,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,219 @@ void main() {
},
);
});
group('multibucket config', () {
final secondaryBucket =
StorageBucket.fromOutputs('Storage Integ Test secondary bucket');
setUpAll(() async {
await configure(amplifyEnvironments['main']!);
await Amplify.Storage.uploadData(
data: StorageDataPayload.bytes(data),
path: StoragePath.fromString(publicPath),
options: StorageUploadDataOptions(bucket: secondaryBucket),
).result;

userIdentityId = await signInNewUser();
identityPath = 'private/$userIdentityId/$name';

await Amplify.Storage.uploadData(
data: StorageDataPayload.bytes(data),
path: StoragePath.fromIdentityId(
(identityId) => 'private/$identityId/$name',
),
options: StorageUploadDataOptions(bucket: secondaryBucket),
).result;

await Amplify.Storage.uploadData(
data: StorageDataPayload.bytes(data),
path: StoragePath.fromString(metadataFilePath),
options: StorageUploadDataOptions(
metadata: metadata,
bucket: secondaryBucket,
),
).result;

addTearDownPaths(
[
StoragePath.fromString(publicPath),
StoragePath.fromString(metadataFilePath),
StoragePath.fromString(identityPath),
],
);
});

group('for file type', () {
testWidgets('to file', (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';

final result = await Amplify.Storage.downloadFile(
path: StoragePath.fromString(publicPath),
localFile: AWSFile.fromPath(downloadFilePath),
options: StorageDownloadFileOptions(bucket: secondaryBucket),
).result;

// Web browsers do not grant access to read arbitrary files
if (!kIsWeb) {
final downloadedFile = await readFile(path: downloadFilePath);
expect(downloadedFile, data);
}

expect(result.localFile.path, downloadFilePath);
expect(result.downloadedItem.path, publicPath);
});
});

testWidgets('from identity ID', (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';
final result = await Amplify.Storage.downloadFile(
path: StoragePath.fromIdentityId(
(identityId) => 'private/$identityId/$name',
),
localFile: AWSFile.fromPath(downloadFilePath),
options: StorageDownloadFileOptions(bucket: secondaryBucket),
).result;

if (!kIsWeb) {
final downloadedFile = await readFile(path: downloadFilePath);
expect(downloadedFile, data);
}
expect(result.localFile.path, downloadFilePath);
expect(result.downloadedItem.path, identityPath);
});

group('with options', () {
testWidgets('useAccelerateEndpoint', (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';

final result = await Amplify.Storage.downloadFile(
path: StoragePath.fromString(publicPath),
options: StorageDownloadFileOptions(
pluginOptions: const S3DownloadFilePluginOptions(
useAccelerateEndpoint: true,
),
bucket: secondaryBucket,
),
localFile: AWSFile.fromPath(downloadFilePath),
).result;

if (!kIsWeb) {
final downloadedFile = await readFile(path: downloadFilePath);
expect(downloadedFile, data);
}
expect(result.localFile.path, downloadFilePath);
expect(result.downloadedItem.path, publicPath);
});

testWidgets('getProperties', (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';
final downloadResult = await Amplify.Storage.downloadFile(
path: StoragePath.fromString(metadataFilePath),
options: StorageDownloadFileOptions(
pluginOptions: const S3DownloadFilePluginOptions(
getProperties: true,
),
bucket: secondaryBucket,
),
localFile: AWSFile.fromPath(downloadFilePath),
).result;

if (!kIsWeb) {
final downloadedFile = await readFile(path: downloadFilePath);
expect(downloadedFile, data);
}
expect(downloadResult.localFile.path, downloadFilePath);
expect(downloadResult.downloadedItem.path, metadataFilePath);
});

testWidgets('unauthorized path', (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';

await expectLater(
() => Amplify.Storage.downloadFile(
path: const StoragePath.fromString('unauthorized/path'),
localFile: AWSFile.fromPath(downloadFilePath),
options: StorageDownloadFileOptions(bucket: secondaryBucket),
).result,
throwsA(isA<StorageAccessDeniedException>()),
);
});
});

group(
'download progress',
() {
testWidgets('reports progress', skip: kIsWeb, (_) async {
final downloadFilePath = '$directory/downloaded-file.txt';
var fractionCompleted = 0.0;
var totalBytes = 0;
var transferredBytes = 0;

await Amplify.Storage.downloadFile(
path: StoragePath.fromString(publicPath),
localFile: AWSFile.fromPath(downloadFilePath),
onProgress: (StorageTransferProgress progress) {
fractionCompleted = progress.fractionCompleted;
totalBytes = progress.totalBytes;
transferredBytes = progress.transferredBytes;
},
options: StorageDownloadFileOptions(bucket: secondaryBucket),
).result;
expect(fractionCompleted, 1.0);
expect(totalBytes, data.length);
expect(transferredBytes, data.length);
});
},
// TODO(Jordan-Nelson): Determine why these are failing on web
skip: kIsWeb,
);

group(
'pause, resume, cancel',
() {
const size = 1024 * 1024 * 6;
const chars = 'qwertyuiopasdfghjklzxcvbnm';
final content = List.generate(size, (i) => chars[i % 25]).join();
final fileId = uuid();
final path = 'public/download-file-pause-$fileId';
setUpAll(() async {
addTearDownPath(StoragePath.fromString(path));
await Amplify.Storage.uploadData(
data: StorageDataPayload.string(content),
path: StoragePath.fromString(path),
options: StorageUploadDataOptions(bucket: secondaryBucket),
).result;
});
testWidgets('can pause', (_) async {
final filePath = '$directory/downloaded-file.txt';
final operation = Amplify.Storage.downloadFile(
localFile: AWSFile.fromPath(filePath),
path: StoragePath.fromString(path),
options: StorageDownloadFileOptions(bucket: secondaryBucket),
);
await operation.pause();
unawaited(
operation.result.then(
(value) => fail('should not complete after pause'),
),
);
await Future<void>.delayed(const Duration(seconds: 15));
});

testWidgets('can resume', (_) async {
final filePath = '$directory/downloaded-file.txt';
final operation = Amplify.Storage.downloadFile(
localFile: AWSFile.fromPath(filePath),
path: StoragePath.fromString(path),
options: StorageDownloadFileOptions(bucket: secondaryBucket),
);
await operation.pause();
await operation.resume();
final result = await operation.result;
expect(result.downloadedItem.path, path);
});
},
// TODO(Jordan-Nelson): Determine why these are failing on web
skip: kIsWeb,
);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,14 @@ class AmplifyStorageS3Dart extends StoragePluginInterface
pluginOptions: options?.pluginOptions,
defaultPluginOptions: const S3DownloadFilePluginOptions(),
);
options = StorageDownloadFileOptions(
final s3options = StorageDownloadFileOptions(
pluginOptions: s3PluginOptions,
bucket: options?.bucket,
);
return download_file_impl.downloadFile(
path: path,
localFile: localFile,
options: options,
options: s3options,
storageOutputs: storageOutputs,
storageS3Service: storageS3Service,
appPathProvider: _appPathProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ S3DownloadFileOperation downloadFile({
cancel: noOp,
);
}

// TODO: add bucket option to function once getURL update has been implemented
Future<S3DownloadFileResult> _downloadFromUrl({
required StoragePath path,
required AWSFile localFile,
Expand All @@ -58,7 +58,7 @@ Future<S3DownloadFileResult> _downloadFromUrl({
// operation.
final downloadedItem = (await storageS3Service.getProperties(
path: path,
options: const StorageGetPropertiesOptions(),
options: StorageGetPropertiesOptions(bucket: options.bucket),
))
.storageItem;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ S3DownloadFileOperation downloadFile({
getProperties: s3PluginOptions.getProperties,
useAccelerateEndpoint: s3PluginOptions.useAccelerateEndpoint,
),
bucket: options.bucket,
);

final downloadDataTask = storageS3Service.downloadData(
Expand Down

0 comments on commit c23fc64

Please sign in to comment.