There are three ways of getting data that was previously uploaded:

## Download File

You can download file to a local directory using `Amplify.Storage.downloadFile`.

You can use the [path_provider](https://pub.dev/packages/path_provider) package to create a local file in the user's documents directory where you can store the downloaded data.

<BlockSwitcher>

<Block name = "Mobile & Desktop">

```dart
import 'package:path_provider/path_provider.dart';

Future<void> downloadToLocalFile(String key) async {
  final documentsDir = await getApplicationDocumentsDirectory();
  final filepath = documentsDir.path + '/example.txt';
  try {
    final result = await Amplify.Storage.downloadFile(
      key: key,
      localFile: AWSFile.fromPath(filepath),
      onProgress: (progress) {
        safePrint('Fraction completed: ${progress.fractionCompleted}');
      },
    ).result;

    safePrint('Downloaded file is located at: ${result.localFile.path}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

</Block>

<Block name = "Web">

On Web, the download process will be handled by the browser. You can provide the downloaded file name by specifying the `path` parameter of `AWSFile.fromPath`. E.g. this instructs the browser to download the file `download.txt`.

```dart
Future<void> downloadToLocalFileOnWeb(String key) async {
  try {
    final result = await Amplify.Storage.downloadFile(
      key: key,
      localFile: AWSFile.fromPath('download.txt'),
    ).result;

    safePrint('Downloaded file: ${result.downloadedItem.key}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

</Block>

</BlockSwitcher>

## Download data

You can download a file to in-memory buffer with `Amplify.Storage.downloadData`:

```dart
Future<void> downloadToMemory(String key) async {
  try {
    final result = await Amplify.Storage.downloadData(
      key: key,
      onProgress: (progress) {
        safePrint('Fraction completed: ${progress.fractionCompleted}');
      },
    ).result;

    safePrint('Downloaded data: ${result.bytes}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

## Generate a download URL

You can get a downloadable URL for the file in storage by its key and access level.

When creating a downloadable URL, you can choose to check if the file exists by setting `validateObjectExistence` to
`true` in `S3GetUrlPluginOptions`. If the file is inaccessible or does not exist, a `StorageException` is thrown.
This allows you to check if an object exists during generating the presigned URL, which you can then use to download
that object.

```dart
Future<String> getDownloadUrl({
  required String key,
  required StorageAccessLevel accessLevel,
}) async {
  try {
    final result = await Amplify.Storage.getUrl(
      key: key,
      options: const StorageGetUrlOptions(
        accessLevel: accessLevel,
        pluginOptions: S3GetUrlPluginOptions(
          validateObjectExistence: true,
          expiresIn: Duration(days: 1),
        ),
      ),
    ).result;
    return result.url.toString();
  } on StorageException catch (e) {
    safePrint('Could not get a downloadable URL: ${e.message}');
    rethrow;
  }
}
```
