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