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="Listener (iOS 11+)">

```swift
let storageOperation = Amplify.Storage.downloadData(
    key: "myKey",
    progressListener: { progress in
        print("Progress: \(progress)")
    }, resultListener: { (event) in
        switch event {
        case let .success(data):
            print("Completed: \(data)")
        case let .failure(storageError):
            print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
    }
})
```

</Block>

<Block name="Combine (iOS 13+)">

```swift
let storageOperation = Amplify.Storage.downloadData(key: "myKey")
let progressSink = storageOperation.progressPublisher.sink { progress in
    print("Progress: \(progress)")
}
let resultSink = storageOperation.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="Listener (iOS 11+)">

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

let storageOperation = Amplify.Storage.downloadFile(
    key: "myKey",
    local: downloadToFileName,
    progressListener: { progress in
        print("Progress: \(progress)")
    }, resultListener: { event in
        switch event {
        case .success:
            print("Completed")
        case .failure(let storageError):
            print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
        }
    })
```

</Block>

<Block name="Combine (iOS 13+)">

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

let storageOperation = Amplify.Storage.downloadFile(
    key: "myKey",
    local: downloadToFileName
)

let progressSink = storageOperation.progressPublisher.sink { progress in
    print("Progress: \(progress)")
}

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

</Block>

</BlockSwitcher>

## Cancel, Pause, Resume

Calls to `downloadData` or `downloadFile` return a reference to the operation 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 operation.

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

You can also pause and then resume the operation.

<Callout>

Note that pause internally uses the `suspend` api of `NSURLSessionTask`, which suspends the task temporarily and does not fully pause the transfer. Complete pausing of task is tracked in this Github issue - https://github.com/aws-amplify/aws-sdk-ios/issues/3668

</Callout>

```swift
storageOperation.pause()
storageOperation.resume()
```

## Generate a download URL

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

<BlockSwitcher>

<Block name="Listener (iOS 11+)">

```swift
Amplify.Storage.getURL(key: "myKey") { event in
    switch event {
    case let .success(url):
        print("Completed: \(url)")
    case let .failure(storageError):
        print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
    }
}
```

</Block>

<Block name="Combine (iOS 13+)">

```swift
let sink = Amplify.Storage.getURL(key: "myKey")
    .resultPublisher
    .sink {
        if case let .failure(storageError) = $0 {
            print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
        }
    }
    receiveValue: { url in
        print("Completed: \(url)")
    }
```

</Block>

</BlockSwitcher>
