[swift4] バックグラウンドでもファイルをインターネットからダウンロード
バックグラウンドでもファイルをインターネットからダウンロードするには以下のコード
AppDelegateにhandleEventsForBackgroundURLSessionを追加するとバックグラウンド処理完了の通知を受け取ることができる。
今回はダウンロードの進捗状況をProgressバーに表示している。
目次
AppDelegate.swift
//MARK: BackgroundDownload private func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { print("Background OK") completionHandler() }
viewController.swift
URLSessionDownloadDelegateを実装しておくこと。
didFinishDownloadingToでダウンロード完了時の処理を記述。tmp fileが保存してあるPathが渡されるので、本来保存したいファイル場所に移動させるなどの処理が必要。
didWriteDataでは進行中のデータが渡されるので適宜Progressバーなどを更新する
didCompleteWithErrorではエラー発生時に呼ばれるので、エラー時の処理を行うこと
class viewContoller: UIViewController,URLSessionDownloadDelegate{ @IBOutlet var progressBar: UIProgressView! //MARK: didload override func viewDidLoad() { super.viewDidLoad() if let url:NSURL = NSURL(string: "https://xxxxxxx") { self.startDownload(url: url as URL, id: "252", name: "テスト") } } //MARK: Progress Bar func resetProgress(){ DispatchQueue.main.async { self.progressBar.isHidden = true self.progressBar.progress = 0 } } //Custom fucntion func startDownload(url : URL, id: String, name: String){ progressBar.isHidden = false let session = initSession(delegate:self) let downloadTask = session.downloadTask(with: url) downloadTask.taskDescription = "\(id),\(name)" downloadTask.resume() //start download } // MARK: - URLSessionDownloadDelegate func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { print("download complete") // ダウンロード完了時の処理 resetProgress() let fileName = downloadTask.originalRequest?.url?.lastPathComponent let localURL = NSURL(string: "file://"+fileInLibraryDirectory(filename: fileName!)) let info = downloadTask.taskDescription?.components(separatedBy: ",") //save file from tmp to local do { try FileManager.default.copyItem(at: location, to: localURL! as URL) //ファイル保存後の処理 } catch (let writeError) { print("error writing file \(location) : \(writeError)") } } func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { // ダウンロード進行中の処理 let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite) // ダウンロードの進捗をログに表示 print(String(format: "%.2f", progress * 100) + "%") // メインスレッドでプログレスバーの更新処理 DispatchQueue.main.async { self.progressBar.setProgress(progress, animated: true) } } func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { // ダウンロードエラー発生時の処理 if error != nil { print("download error: \(error)") } } //MARK:Library folder func getLibraryURL() -> NSURL { let libraryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0] return libraryURL as NSURL } func fileInLibraryDirectory(filename: String) -> String { let folderName = "media" createDirectory(foldername: folderName) let fileURL = getLibraryURL().appendingPathComponent("\(folderName)/\(filename)") return fileURL!.path } //MARK:Create Directory func createDirectory(foldername : String){ let fileManager = FileManager.default let paths = (NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(foldername) if !fileManager.fileExists(atPath: paths){ try! fileManager.createDirectory(atPath: paths, withIntermediateDirectories: true, attributes: nil) }else{ print("Already dictionary created.") } } }