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


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です