[swift4] How to download files from Internet as background

How to download files from Internet as background, is below code

Can get completionheader by adding “handleEventsForBackgroundURLSession” at AppDelegate when download completed at background

in this case, Download progress info is displayed at progress bar

目次

AppDelegate.swift


    //MARK: BackgroundDownload
    private func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        
        print("Background OK")
        completionHandler()
        
    }

viewController.swift

Have to setup URLSessionDownloadDelegate

on didFinishDownloadingTo, run method when download complete.
for instance, move tmp downloaded file to local

on didWriteData, get download progress info, then update progress bar.

on didCompleteWithError, call this method in the case of error.



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)
            //other method after saving file to local
            
        } 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.")
        }
    }
    
}


コメントを残す

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