Observe Progress of Data Download in Swift

Observe progress of Data download in Swift?

Don't use Data(contentsOf: url) to make synchronous request for urls that are not local resources. You should use URLSession.To observe the progress you need to set urlsessiondownloaddelegate https://developer.apple.com/documentation/foundation/urlsessiondownloaddelegate and to monitor the progress, use the method

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

https://developer.apple.com/documentation/foundation/urlsessiondownloaddelegate/1409408-urlsession

Find the Download Progress of a file in swift

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

get progress from dataTaskWithURL in swift

you can use this code for showing download process with progress bar with its delegate functions.

import UIKit

class ViewController: UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate{

@IBOutlet weak var progress: UIProgressView!

var buffer:NSMutableData = NSMutableData()
var session:NSURLSession?
var dataTask:NSURLSessionDataTask?
let url = NSURL(string:"http://i.stack.imgur.com/b8zkg.png" )!
var expectedContentLength = 0

override func viewDidLoad() {
super.viewDidLoad()
progress.progress = 0.0
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let manqueue = NSOperationQueue.mainQueue()
session = NSURLSession(configuration: configuration, delegate:self, delegateQueue: manqueue)
dataTask = session?.dataTaskWithRequest(NSURLRequest(URL: url))
dataTask?.resume()

// Do any additional setup after loading the view, typically from a nib.
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {

//here you can get full lenth of your content
expectedContentLength = Int(response.expectedContentLength)
println(expectedContentLength)
completionHandler(NSURLSessionResponseDisposition.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {

buffer.appendData(data)

let percentageDownloaded = Float(buffer.length) / Float(expectedContentLength)
progress.progress = percentageDownloaded
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
//use buffer here.Download is done
progress.progress = 1.0 // download 100% complete
}
}

How to link Firebase download file with a progress view?

Several thoughts:

  • Don't download in memory and then write to disk--we have a method that downloads straight to the file system
  • Attach listeners rather than a single completion handler--that way you can listen to progress updates
  • Use something like MBProgressHUD to show an incremental progress bar
  • No need to set the isNetworkActivityIndicatorVisible as we'll do that for you

Putting that together, you get something like:

// Create a reference to the file we want to download
let starsRef = storageRef.child("images/stars.jpg")

// Start the download (in this case writing to a file)
let downloadTask = storageRef.write(toFile: localURL)

// Start progress indicator

// Observe changes in status
downloadTask.observe(.progress) { snapshot in
// Download reported progress
let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
/ Double(snapshot.progress!.totalUnitCount)
// Update the progress indicator
}

downloadTask.observe(.success) { snapshot in
// Download completed successfully
// Stop progress indicator
}

// Errors only occur in the "Failure" case
downloadTask.observe(.failure) { snapshot in
// An error occurred!
// Stop progress indicator
}

Showing the file download progress with NSURLSessionDataTask

You need to implement following delegates:

<NSURLSessionDataDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate>

Also need to create two properties:

@property (nonatomic, retain) NSMutableData *dataToDownload;
@property (nonatomic) float downloadSize;

- (void)viewDidLoad {
[super viewDidLoad];

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];

NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

NSURL *url = [NSURL URLWithString: @"your url"];
NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url];

[dataTask resume];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
completionHandler(NSURLSessionResponseAllow);

progressBar.progress=0.0f;
_downloadSize=[response expectedContentLength];
_dataToDownload=[[NSMutableData alloc]init];
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
[_dataToDownload appendData:data];
progressBar.progress=[ _dataToDownload length ]/_downloadSize;
}


Related Topics



Leave a reply



Submit