Objective C: Downloading File With Progress Bar
Using AFNetworking,
here progress is the UIProgressview
#import //add to the header of class
-(void)downloadShowingProgress
{
progress.progress = 0.0;
currentURL=@"http://www.selab.isti.cnr.it/ws-mate/example.pdf";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:currentURL]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"MY_FILENAME_WITH_EXTENTION.pdf"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, NSUInteger totalBytesRead, NSUInteger totalBytesExpectedToRead) {
progress.progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];
[operation setCompletionBlock:^{
NSLog(@"downloadComplete!");
}];
[operation start];
}
Using NSURLConnection
-(void)downloadWithNsurlconnection
{
NSURL *url = [NSURL URLWithString:currentURL];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
receivedData = [[NSMutableData alloc] initWithLength:0];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
progress.hidden = NO;
[receivedData setLength:0];
expectedBytes = [response expectedContentLength];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
float progressive = (float)[receivedData length] / (float)expectedBytes;
[progress setProgress:progressive];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse: (NSCachedURLResponse *)cachedResponse {
return nil;
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:[currentURL stringByAppendingString:@".mp3"]];
NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[receivedData writeToFile:pdfPath atomically:YES];
progress.hidden = YES;
}
Multiple downloading progress bar objective c
Well...after few days thinking about my issue, I realize I was doing too many database access and because of that my app freeze.
I solved it passing to my HTTPConnection object, an instance of the progress bar I want to manage. And I save the progress download/upload only when finishing.
So that is my solution:
In HTTPConnection:
+ (void)setProgressBar:(UIProgressView *)progress
{
[downloadConnection setProgressBar:progress];
}
//CODE...
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
if (self.progressBar) {
self.progressBar.progress = progress;
}
if (progress == 1.0) {
[self saveProgressInDatabase:[NSNumber numberWithFloat:progress]];
}
}
And in my message list:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Message *info = [_fetchedResultsController objectAtIndexPath:indexPath];
//MORE CODE...
if (([info contentSize]!=NULL)&&([[info uploaded]floatValue]<1.0)) {
[HTTPConnection setProgressBar:cell.progressBar];
[cell.progressBar setHidden:NO];
} }
Thanks for your help!
Objective c: download a file with progress view
You can get expected total file size in following callback method of NSURLconnection,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
expectedTotalSize = response.expectedContentLength;
}
then in the following callback method you can calculate how much data has been recieved,
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
recievedData += data.length;
}
And you can use UIProgressView to show current downloading status on the screen.
ProgressView for Downloading some files in Object-C
I think that it is related to threads and how the main thread will refresh the view.
Two cases can occur:
You are on the main thread when calling this method
In such case, you do not allow the main thread to execute refresh routines. Move all this download to a background queue using GCD, and call back the main thread like explained in pt.2.
To put everything in a background queue, you could call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ {
// your download code goes here
});
Or, You are already on the background thread, then use the following lines to call back to the main thread:
dispatch_async(dispatch_get_main_queue(), ^ {
progressView.progress = (float)i/(float)7;
});
Final answer:
- (IBAction)download:(id)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ {
// Determile cache file path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
progressSlider.progress = 0.0;
for (i=0;i<=7;i++) {
//Updating progressView and progressLabel
progressLabel.text = [NSString stringWithFormat:@"Загружено: %d из 7",i];
dispatch_async(dispatch_get_main_queue(), ^ {
progressView.progress = (float)i/(float)7;
});
NSString *filePath = [NSString stringWithFormat:@"%@/avto-0-%d.html", [paths objectAtIndex:0],i];
// Download and write to file
NSString *mustUrl = [NSString stringWithFormat:@"http://www.mosgortrans.org/pass3/shedule.php?type=avto&%@", [listOfAvtoUrl objectAtIndex:i]];
NSURL *url = [NSURL URLWithString:mustUrl];
NSData *urlData = [NSData dataWithContentsOfURL:url];
[urlData writeToFile:filePath atomically:YES];
}
});
}
Showing the file download progress with NSURLSessionDataTask
You need to implement following delegates:
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;
}
How can I link a file download with a Progress View
Here is complete working example for you:
import UIKit
class ViewController: UIViewController, NSURLSessionDownloadDelegate {
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var progressCount: UILabel!
var task : NSURLSessionTask!
var percentageWritten:Float = 0.0
var taskTotalBytesWritten = 0
var taskTotalBytesExpectedToWrite = 0
lazy var session : NSURLSession = {
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
config.allowsCellularAccess = false
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
return session
}()
override func viewDidLoad() {
progressBar.setProgress(0.0, animated: true) //set progressBar to 0 at start
}
@IBAction func doElaborateHTTP (sender:AnyObject!) {
progressCount.text = "0%"
if self.task != nil {
return
}
let s = "http://www.qdtricks.com/wp-content/uploads/2015/02/hd-wallpapers-1080p-for-mobile.png"
let url = NSURL(string:s)!
let req = NSMutableURLRequest(URL:url)
let task = self.session.downloadTaskWithRequest(req)
self.task = task
task.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
println("downloaded \(100*writ/exp)")
taskTotalBytesWritten = Int(writ)
taskTotalBytesExpectedToWrite = Int(exp)
percentageWritten = Float(taskTotalBytesWritten) / Float(taskTotalBytesExpectedToWrite)
progressBar.progress = percentageWritten
progressCount.text = String(format: "%.01f", percentageWritten*100) + "%"
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
// unused in this example
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
println("completed: error: \(error)")
}
// this is the only required NSURLSessionDownloadDelegate method
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
let documentsDirectoryURL = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as! NSURL
println("Finished downloading!")
println(documentsDirectoryURL)
var err:NSError?
// Here you can move your downloaded file
if NSFileManager().moveItemAtURL(location, toURL: documentsDirectoryURL.URLByAppendingPathComponent(downloadTask.response!.suggestedFilename!), error: &err) {
println("File saved")
} else {
if let err = err {
println("File not saved.\n\(err.description)")
}
}
}
}
You can use NSURLSessionDownloadDelegate
to achieve this whose method will be called when user downloading data.
This will show you the process into progressCount
label and the progressBar
will show process as count will increment. you can modify this as per your need.
You can download this example from HERE.
how to use the progress bar in the iphone app
first you create IBOutlet in .h file
IBOutlet UIProgressView * threadProgressView;
Then in .m file in viewdidload first set progress to 0.0 and then call makeMyProgressMoving method
threadProgressView.progress = 0.0;
[self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];
then add below method
- (void)makeMyProgressBarMoving {
float actual = [threadProgressView progress];
if (actual < 1) {
threadProgressView.progress = actual + ((float)recievedData/(float)xpectedTotalSize);
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(makeMyProgressBarMoving) userInfo:nil repeats:NO];
}
else{
}
}
also give your review for answer. is it useful to you?
Related Topics
Delete All Keys from a Nsuserdefaults Dictionary iOS
How to Convert a Double into a Byte Array in Swift
Decoding JSON Web Tokens in Swift
Swift Different Images For Annotation
Saving Image and Then Loading It in Swift (Ios)
Default Keyword in Swift Parameter
iOS Uinavigationbar Button Remains Faded After Segue Back
How to Get the Console Logs from the iOS Simulator
How to Change Device Volume on iOS - Not Music Volume
Ble Peripheral Disconnects When Navigating to Different Viewcontroller
How to Fix "No Valid 'Aps-Environment' Entitlement String Found for Application" in Xcode 4.3
Changing the Height of the Navigation Bar iOS Swift
How to Dismiss the Keyboard When Editing a Uitextfield