Article

Downloading Files from Websites ファイルをウェブサイトからダウンロードする

Download files directly to the filesystem. ファイルを直接にファイルシステムにダウンロードします。

Overview 概要

For network resources that are already stored as files, like images and documents, you can use download tasks to fetch these items directly to the local filesystem. 既にファイルとして格納されるネットワークリソース、画像および書類などに対して、あなたはダウンロードタスクを使ってそれらの項目を直接にローカルファイルシステムに取って来ることができます。

For Simple Downloads, Use a Completion Handler 単純なダウンロードのために、完了ハンドラを使ってください

To download files, you create a URLSessionDownloadTask from a URLSession. If you don’t care about receiving progress updates or other delegate callbacks during the download, you can use a completion handler. The task calls the completion handler when the download ends, either at the end of a successful download or when downloading fails. ファイルをダウンロードするには、あなたはURLSessionDownloadTaskURLSessionから作成します。あなたが進捗最新情報を受け取るまたは他のコールバックについてそのダウンロードの間に関心がないならば、あなたは完了ハンドラを使うことができます。タスクは、完了ハンドラをダウンロードが終わる時に呼び出します、うまくいったダウンロードの終わりでまたはダウンロードが失敗する時のどちらかで。

Your completion handler may receive a client-side error, indicating a local problem like not being able to reach the network. If there is no client-side error, you also receive a URLResponse, which you should inspect to ensure that it indicates a successful response from the server. あなたの完了ハンドラは、ネットワークに接続できないなどのローカルな問題を指し示している、クライアント側エラーを受け取るかもしれません。クライアント側エラーがないならば、あなたはまたURLResponseを受け取ります、それは、あなたが検査して、それがサーバーからのある成功した応答を指し示すことを保証すべきものです。

If the download is successful, your completion handler receives a URL indicating the location of the downloaded file on the local filesystem. This storage is temporary. If you want to preserve the file, you must copy or move it from this location before returning from the completion handler. ダウンロードが成功するならば、あなたの完了ハンドラはダウンロードされたファイルの位置をローカルファイルシステム上で指し示しているURLを受け取ります。このストレージ(貯蔵)は、一時的です。あなたがそのファイルを保存しておきたいならば、あなたはそれをこの場所からコピーまたは移動する必要があります、完了ハンドラから返る前に。

Listing 1 shows a simple example of creating a download task with a completion handler. If no errors are indicated, the completion handler moves the downloaded file to the app’s Documents directory. Start the task by calling resume(). コード出力 1 は、ダウンロードタスクを完了ハンドラで作成するある単純な例を示します。ひとつのエラーも指し示されないならば、完了ハンドラはこのダウンロードされたファイルをアプリのもつDocumentsディレクトリに移動します。このタスクをresume()を呼び出すことによって開始してください。

Listing 1 Creating a download task with a completion handler コード出力 1 ダウンロードタスクを完了ハンドラで作成する

let downloadTask = URLSession.shared.downloadTask(with: url) {
    urlOrNil, responseOrNil, errorOrNil in
    // check for and handle errors:
    // * errorOrNil should be nil
    // * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
    
    guard let fileURL = urlOrNil else { return }
    do {
        let documentsURL = try
            FileManager.default.url(for: .documentDirectory,
                                    in: .userDomainMask,
                                    appropriateFor: nil,
                                    create: false)
        let savedURL = documentsURL.appendingPathComponent(fileURL.lastPathComponent)
        try FileManager.default.moveItem(at: fileURL, to: savedURL)
    } catch {
        print ("file error: \(error)")
    }
}
downloadTask.resume()

To Receive Progress Updates, Use a Delegate 進捗最新情報を受け取るには、委任先を使ってください

If you want to receive progress updates as the download proceeds, you must use a delegate. Instead of receiving the results in a completion handler, you receive callbacks to your implementations of methods from the URLSessionTaskDelegate and URLSessionDownloadDelegate protocols. あなたが進捗更新をダウンロードが進行するにつれて受け取りたいならば、あなたはある委任先を使わなければなりません。完了ハンドラにおいて結果を受け取る代わりに、あなたは、URLSessionTaskDelegateURLSessionDownloadDelegateプロトコル由来のメソッドのあなたの実装へのコールバックを受け取ります。

Create your own URLSession instance, and set its delegate property. Listing 2 shows a lazily instantiated urlSession property that sets self as its delegate. あなた独自のURLSessionインスタンスを作成して、そしてそれのdelegateプロパティを設定してください。コード出力 2 は、遅延にインスタンス化されるurlSessionプロパティを示します、それはselfをそれの委任先として設定します。

Listing 2 Creating a URL session with a delegate コード出力 2 URLセッションをある委任先で作成する

private lazy var urlSession = URLSession(configuration: .default,
                                         delegate: self,
                                         delegateQueue: nil)

To start downloading, use this URLSession to create a URLSessionDownloadTask, and then start the task by calling resume(), as shown in Listing 3. ダウンロードを開始するには、このURLSessionを使ってURLSessionDownloadTaskを作成します、それからそのタスクをresume()を呼び出すことによって開始します、コード出力 3で示されるように。

Listing 3 Creating and starting a download task that uses a delegate コード出力 3 委任先を使用するダウンロードタスクを作成して開始する

private func startDownload(url: URL) {
    let downloadTask = urlSession.downloadTask(with: url)
    downloadTask.resume()
    self.downloadTask = downloadTask
}

Receive Progress Updates 進捗最新情報を受け取る

Once the download starts, you receive periodic progress updates in the URLSessionDownloadDelegate method urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:). You can use the byte counts provided by this callback to update a progress UI in your app. 一旦ダウンロードが始まるならば、あなたは周期的な進捗最新情報をURLSessionDownloadDelegateのメソッドurlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)において受け取ります。あなたは、このコールバックによって提供されるバイト計数を使って、進捗UIをあなたのアプリにおいて更新できます。

Listing 4 shows an implementation of this callback method. This implementation calculates the fractional progress of the download, and uses it to update a label that shows progress as a percentage. Because the callback is performed on an unknown Grand Central Dispatch queue, you must explicitly perform the UI update on the main queue. コード出力 4 は、このコールバックメソッドの実装を示します。この実装は、ダウンロードの分数の進捗を計算します、そしてそれを使って、百分率として進捗を示すあるラベルを更新します。コールバックが未知の「グランドセントラルディスパッチ」キュー上で実行されることから、あなたは明示的にUI更新をメインキュー上で実行する必要があります

Listing 4 Using a delegate method to update download progress in a UI コード出力 4 委任先メソッドを使ってタウンロード進捗をUIにおいて更新する

func urlSession(_ session: URLSession,
                downloadTask: URLSessionDownloadTask,
                didWriteData bytesWritten: Int64,
                totalBytesWritten: Int64,
                totalBytesExpectedToWrite: Int64) {
     if downloadTask == self.downloadTask {
        let calculatedProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
        DispatchQueue.main.async {
            self.progressLabel.text = self.percentFormatter.string(from:
                NSNumber(value: calculatedProgress))
    }
}

Handle Download Completion or Errors in Your Delegate ダウンロード完了またはエラーをあなたの委任先において取り扱う

When you use a delegate instead of a completion handler, you handle the completion of the download by implementing urlSession(_:downloadTask:didFinishDownloadingTo:). Check the downloadTask’s response property to ensure that the server response indicates success. If so, the location parameter provides a local URL where the file has been stored. This location is valid only until the end of the callback. This means you must either read the file immediately, or move it to another location such as the app’s Documents directory before you return from the callback method. Listing 5 shows how to preserve the downloaded file. あなたがある委任先を完了ハンドラの代わりに使う場合、あなたはダウンロードの完了をurlSession(_:downloadTask:didFinishDownloadingTo:)を実装することによって取り扱います。downloadTaskのもつresponseプロパティを確認することで、サーバー応答が成功を指し示すことを確実にしてください。もしそうならば、locationパラメータはそこにおいてファイルが格納されているローカルURLを提供します。この位置は、コールバックの終わりまでのみ有効です。これはあなたが、ファイルを直接に読み出す、またはそれを別の場所にたとえばアプリのもつDocumentsディレクトリに移動する、どちらかをあなたがコールバックメソッドから返る前にしなければならないことを意味します。コード出力 5 はダウンロードファイルを取っておく方法を示します。

Listing 5 Saving the downloaded file in the delegate callback コード出力 5 委任先コールバックにおいてダウンロードされたファイルを保存する

func urlSession(_ session: URLSession,
                downloadTask: URLSessionDownloadTask,
                didFinishDownloadingTo location: URL) {
    // check for and handle errors:
    // * downloadTask.response should be an HTTPURLResponse with statusCode in 200..<299


    do {
        let documentsURL = try
            FileManager.default.url(for: .documentDirectory,
                                    in: .userDomainMask,
                                    appropriateFor: nil,
                                    create: false)
        let savedURL = documentsURL.appendingPathComponent(
            location.lastPathComponent)
        try FileManager.default.moveItem(at: location, to: savedURL)
    } catch {
        // handle filesystem error
    }
}

If a client-side error occurs, your delegate receives it in a callback to the urlSession(_:task:didCompleteWithError:) delegate method. On the other hand, if the download completes successfully, this method is called after urlSession(_:downloadTask:didFinishDownloadingTo:) and the error is nil. クライアント側エラーが発生するならば、あなたの委任先はそれをurlSession(_:task:didCompleteWithError:)委任先メソッドへのコールバックにおいて受け取ります。言い換えれば、ダウンロードがうまく完了するならば、このメソッドはurlSession(_:downloadTask:didFinishDownloadingTo:)の後に呼び出されます、そしてエラーはnilです。

See Also 参照

Downloading ダウンロード