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