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 it is in the background.

Get your tech solution built by top industry experts!!!

Download Files Using URLSessionDownloadTask

Creating an object of URLSessionDownloadTask

Create an object of URLSessionDownloadTask 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 it in the 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 the user put your application in background mode then handleEventsForBackground URLSessionDownloadTask 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 the 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()
 }
 }

Posted

in

by

Comments

Leave a Reply

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