Find the Download Progress of a file in swift

17,072

Solution 1

The progress status can be calculated in

URLSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)

This is a one of three required methods of protocol NSURLSessionDownloadDelegate. In my case the code of the method looks like this:

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    // println("download task did write data")

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

    dispatch_async(dispatch_get_main_queue()) {
        self.progressDownloadIndicator.progress = progress
    }
}

I've created a small project, which implements three different approaches:

  • download synchronously
  • download asynchronously
  • download with progress

Check it out: http://goo.gl/veRkA7

Solution 2

You can simply observe progress property of the URLSessionDataTask object. And you don't need to calculate the progress as other answers suggest here. There is a fractionCompleted property on the Progress.

Playground example:

import Foundation
import PlaygroundSupport

let page = PlaygroundPage.current
page.needsIndefiniteExecution = true

let url = URL(string: "https://source.unsplash.com/random/4000x4000")!
let task = URLSession.shared.dataTask(with: url) { _, _, _ in
  page.finishExecution()
}

// Don't forget to invalidate the observation when you don't need it anymore.
let observation = task.progress.observe(\.fractionCompleted) { progress, _ in
  print(progress.fractionCompleted)
}

task.resume()

Solution 3

Assuming you are downloading a file, there is a subclass of NSURLSessionTask for the just that, called NSURLSessionDownloadTask. Below is an excerpt from the NSURLSession documentation on a specific function:

Periodically informs the delegate about the download’s progress.

func URLSession(_ session: NSURLSession,
    downloadTask downloadTask: NSURLSessionDownloadTask,
    didWriteData bytesWritten: Int64,
    totalBytesWritten totalBytesWritten: Int64,
    totalBytesExpectedToWrite totalBytesExpectedToWrite: Int64
)

For example, you could output the progress to the console by doing:

println("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
Share:
17,072
loopidio
Author by

loopidio

Updated on July 23, 2022

Comments

  • loopidio
    loopidio almost 2 years

    I have searched but haven't found a relevant answer only in Objective C. Is there a way to find the progress of the download of a file in Swift, so that to show it to user? I am new to iOS programming and I have tried with NSURLSession but without success.

    EDIT: I have used this method as seen in this post, but I can't seem to understand how to get the progress status:

    func downloadFile(page: NSString){
        finished = false
        var statusCode:Int = 0
        println("Download starting")
        let url = NSURL(string: page)
    
        let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
    
            if error != nil {
                println("download failed with error \(error?.localizedDescription)")
            } else {
                println("Expected Content-Length \(response.expectedContentLength)")
                self.contentLength = response.expectedContentLength
                if let httpResponse = response as? NSHTTPURLResponse {
                    println("Status Code of number \(self.countDownload) is \(httpResponse.statusCode)")
                    statusCode = httpResponse.statusCode
                }
            }
        }
        task.resume()
    }
    

    Thank you in advance

  • dar512
    dar512 about 9 years
    I believe this only works if you use the delegate methods and not a closure.
  • Jeffrey
    Jeffrey about 9 years
    @dar512 That's true. I should note I don't believe there is any way to find the progress if you're using a closure.