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

## Download data

You can download to in-memory buffer [Data](https://developer.apple.com/documentation/foundation/data) object with `Amplify.Storage.downloadData`:

<BlockSwitcher>

<Block name="Async/Await">

```swift
let downloadTask = Amplify.Storage.downloadData(key: "ExampleKey")
Task {
    for await progress in await downloadTask.progress {
        print("Progress: \(progress)")
    }
}
let data = try await downloadTask.value
print("Completed: \(data)")
```

</Block>

<Block name="Combine">

```swift
let downloadTask = Amplify.Storage.downloadData(key: "ExampleKey")
let progressSink = downloadTask
    .inProcessPublisher
    .sink { progress in
        print("Progress: \(progress)")
    }

let resultSink = downloadTask
    .resultPublisher
    .sink {
        if case let .failure(storageError) = $0 {
            print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
        }
    }
    receiveValue: { data in
        print("Completed: \(data)")
    }
```

</Block>

</BlockSwitcher>

## Download to file

You can download to a file [URL](https://developer.apple.com/documentation/foundation/url) with `Amplify.Storage.downloadFile`:

<BlockSwitcher>

<Block name="Async/Await">

```swift
let downloadToFileName = FileManager.default.urls(
    for: .documentDirectory,
    in: .userDomainMask
)[0].appendingPathComponent("myFile.txt")

let downloadTask = Amplify.Storage.downloadFile(
    key: "myKey",
    local: downloadToFileName,
    options: nil
)
Task {
    for await progress in await downloadTask.progress {
        print("Progress: \(progress)")
    }
}
try await downloadTask.value
print("Completed")
```

</Block>

<Block name="Combine">

```swift
let downloadToFileName = FileManager.default.urls(
    for: .documentDirectory,
    in: .userDomainMask
)[0].appendingPathComponent("myFile.txt")

let downloadTask = Amplify.Storage.downloadFile(
    key: "myKey",
    local: downloadToFileName,
    options: nil
)
let progressSink = downloadTask
    .inProcessPublisher
    .sink { progress in
        print("Progress: \(progress)")
    }

let resultSink = downloadTask
    .resultPublisher
    .sink {
        if case let .failure(storageError) = $0 {
            print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
        }
    }
    receiveValue: {
        print("Completed")
    }
```

</Block>

</BlockSwitcher>

## Generate a download URL

You can also retrieve a URL for the object in storage:

```swift
let url = try await Amplify.Storage.getURL(key: "ExampleKey")
print("Completed: \(url)")
```

When creating a downloadable URL, you can choose to check if the file exists by setting `validateObjectExistence` to
`true` in `AWSStorageGetURLOptions`. If the file is inaccessible or does not exist, a `StorageError` 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.

```swift
let url = try await Amplify.Storage.getURL(
    key: "ExampleKey",
    options: .init(
        pluginOptions: AWSStorageGetURLOptions(
            validateObjectExistence: true
        )
    )
)
```

## Cancel, Pause, Resume

Calls to `downloadData` or `downloadFile` return a reference to the task that is actually performing the download.

To cancel the download (for example, in response to the user pressing a **Cancel** button), you simply call `cancel()` on the download task.

```swift
func cancelDownload() {
    downloadTask.cancel()
}
```

You can also pause and then resume the task.

```swift
downloadTask.pause()
downloadTask.resume()
```


<Callout>

Download tasks are run using `URLSessionTask` instances internally. You can learn more about them in [Apple's official documentation](https://developer.apple.com/documentation/foundation/urlsessiontask).

</Callout>