[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.")
}
}
}