How to Download Files Using URLSessionDownloadTask

Here, we are going to discuss how to download large files and save partial data even when the app is terminated and also updating the view when is in the background.

Creating an object of URLSession

Create an object of URLSession which you have to config the identifier using URLSessionConfiguration after make isDiscretionary true so that we will enable downloading with performance in the background state.

    private lazy var urlSession: URLSession = {

        let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier ?? "").backgrouns")

        config.isDiscretionary = true

        config.sessionSendsLaunchEvents = true

        return URLSession(configuration: config, delegate: self, delegateQueue: nil)

    }()

Pursuing that pass URL from which you want to download the using downloadTask method of URL session class

urlSession.downloadTask(with: URL(string: "your url")!)

Then file downloading will start to track the download data likes totalBytesExpectedToWrite, totalBytesWritten from that you can calculate how much data is downloaded with this delegate method

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

        

        print(totalBytesExpectedToWrite)

        print(totalBytesWritten)

        let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)

        debugPrint("Progress \("") \(progress)")

    }

In that case, when your file is downloaded you can save in directory of your app.

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
 didFinishDownloadingTo location: URL) {
 guard let httpResponse = downloadTask.response as? HTTPURLResponse,
 (200...299).contains(httpResponse.statusCode) else {
 print ("server error")
 return
 }
 do {
 let documentsURL = try
 FileManager.default.url(for: .documentDirectory,
 in: .userDomainMask,
 appropriateFor: nil,
 create: false)
 let savedURL = documentsURL.appendingPathComponent(
 "\(randomString(length: 2)).pdf")
 print(location)
 print(savedURL)
 try FileManager.default.moveItem(at: location, to: savedURL)
 } catch {
 print ("file error: \(error)")
 }
 }
 func randomString(length: Int) -> String {
 let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 let len = UInt32(letters.length)
 var randomString = ""
 for _ in 0 ..< length {
 let rand = arc4random_uniform(len)
 var nextChar = letters.character(at: Int(rand))
 randomString += NSString(characters: &nextChar, length: 1) as String
 }
 return randomString
 }

Imagine user put your application in background mode then handleEventsForBackgroundURLSession method call of the app delegate class

var backgroundCompletionHandler : ( () -> Void )?
 func app (_ app: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
 debugPrint("handleEventsForBackgroundURLSession: \(identifier)")
 backgroundCompletionHandler = completionHandler
 }

Once the download is finished in background state then you have to update the view in the main thread

 func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
 DispatchQueue.main.async {
 guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
 let backgroundCompletionHandler =
 appDelegate.backgroundCompletionHandler else {
 return
 }
 backgroundCompletionHandler()
 }
 }

Last Update: February 13, 2019  

December 18, 2018   97   Nandini R    Swift Significance    
Total 0 Votes:
0

Tell us how can we improve this post?

+ = Verify Human or Spambot ?

Leave a Reply

Your email address will not be published. Required fields are marked *

Facebook
Twitter
INSTAGRAM
LinkedIn