I want to download large file using AFNetworking 3. But I need to resume download while there is any interruption like internet loss or any other things. If any interrupts while downloading I want to start download from where it stop early. Is it possible using AFNetworking or do I use any other libraries? Please anybody help me.
Here is my code.
NSURLRequest *request = [NSURLRequest requestWithURL:formattedURL];
//Watch the manager to see how much of the file it's downloaded
[manager setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
//Convert totalBytesWritten and totalBytesExpectedToWrite into floats so that percentageCompleted doesn't get rounded to the nearest integer
CGFloat written = totalBytesWritten;
CGFloat total = totalBytesExpectedToWrite;
CGFloat percentageCompleted = written/total;
//Return the completed progress so we can display it somewhere else in app
//progressBlock(percentageCompleted);
NSLog(#"Percentage Completed : %f",percentageCompleted);
[self updateProgressBar:percentageCompleted];
}];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
//Getting the path of the document directory
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
NSURL *fullURL = [documentsDirectoryURL URLByAppendingPathComponent:#"3511_1464694276.zip"];
//If we already have a video file saved, remove it from the phone
return fullURL;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
if (!error) {
//If there's no error, return the completion block
//completionBlock(filePath);
} else {
//Otherwise return the error block
//errorBlock(error);
}
}];
[downloadTask resume];
Read more about it here : https://github.com/AFNetworking/AFNetworking
And try to ask questions when you have written some code or tried something on your own.
Download file with progress :
- (IBAction)downloadAudio:(id)sender {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://101songs.com/fileDownload/Songs/0/26958.mp3"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[_myProgressView setProgress:downloadProgress.fractionCompleted];
});
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
// Do operation after download is complete
}];
[downloadTask resume];
}
Related
i want to configure progress bar but my url can not give me total size of my image . i follow this tutorial http://tarikfayad.com/afnetworking-downloading-files-with-progress/
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
//Most URLs I come across are in string format so to convert them into an NSURL and then instantiate the actual request
NSURL *formattedURL = [NSURL URLWithString:#"http://www.wallpapers13.com/wp-content/uploads/2016/04/Sunset-Large-Chinese-wall-Desktop-Wallpaper-HD-5250x3344.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:formattedURL];
[manager setDownloadTaskDidWriteDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDownloadTask * _Nonnull downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
//CGFloat w = totalBytesWritten;
CGFloat t = totalBytesExpectedToWrite;
//CGFloat percentageCompleted = w/t;
NSLog(#"%f",t); // Error retun -1
}];
NSURLSessionDownloadTask *download = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
//
//Getting the path of the document directory
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
NSURL *fullURL = [documentsDirectoryURL URLByAppendingPathComponent:#"image1.jpg"];
//If we already have a video file saved, remove it from the phone
[self removeVideoAtPath:fullURL];
return fullURL;
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
if (!error) {
//If there's no error, return the completion block
[self completionBlock:(NSString *)filePath];
} else {
//Otherwise return the error block
[self errorBlock:error];
}
}];
[download resume];
Try this:
NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager * manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL * URL = [NSURL URLWithString:#"http://static1.visitfinland.com/wp-content/uploads/Header_Linnunlaulu_ruska_autumn.jpg"];
NSURLRequest * request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask * downloadTask = [manager downloadTaskWithRequest:request
progress:^(NSProgress * _Nonnull downloadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
// here you will be able to set progress to your progress view
[yourProgressView setProgress:downloadProgress.fractionCompleted];
});
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL * documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:NO
error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse * response, NSURL * filePath, NSError * error) {
}];
[downloadTask resume];
If the totalBytesExpectedToWrite is -1, then you have some issues on your server configuration, because it is not responding the total size of your image.
Without the total size it's not possible to do a correct progress bar, you can only display some activity indicator (which just indicating that something it happening, but does not give a feedback when it will be finished).
I recommend to take a look your server settings (especially to setup the Content-Length header on the right way).
i am working on multiple images download. but after sometime my ui hangs and memory constantly increases.
i am using afnetworking for downloading the images.
-(void)download:(NSString *)url
{
NSURL *URL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [SessionManager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
documentsDirectoryURL = [documentsDirectoryURL URLByAppendingPathComponent:#"Assets"];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//NSLog(#"File downloaded to: %#", filePath);
[[ePackDownloader sharedClient] downloadComplete:url];
}];
[downloadTask resume];
}
still new to objective C i have discover the amazing AFNetworking network class.
Using the dic i have my code which download my file and write into the NSDocumentDirectory
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://myAdress/Menu.plist"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(#"File downloaded to: %#", filePath);
NSDictionary *dicMenuPlist = [NSDictionary dictionaryWithContentsOfFile:[filePath path]];
NSLog(#"Dic Menu Plist = %#",dicMenuPlist);
}];
[downloadTask resume];
this works fine but when i change something in my Menu.plist file the changes does not appear, i have to delete my app then download the file that has changed.
I do not understand why i have to do this.
Can someone help me please ?
The answer given here.
Delete the existing file in the destination block.
destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
NSURL *fileURL = [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if ([httpResponse statusCode] == 200) {
// delete existing file (using file URL above)
}
return fileURL;
}
Default method AFNetworking 3.0 don't refresh that you downloader files.
If you want rewrite this file in Objective-C +iOS9.0, you need do that:
- (NSURLSessionDownloadTask *) downloadDocsFromUrl:(NSString *) url withSuccesBlock:(DocModelBlock) docModelBlock withErrorBlock:(ErrorBlock) errorBlock {
NSURL *URL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [self.sessionManager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSURL *documentsDirectoryURL = [fileManager URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:&error];
if ([httpResponse statusCode] == 200) {
NSURL *urlPath = [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
if ([fileManager fileExistsAtPath:urlPath.path]) {
[fileManager removeItemAtPath:urlPath.path error:&error];
}
}
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
if (error) {
errorBlock(error);
} else {
docModelBlock(filePath);
}
}];
[downloadTask resume];
return downloadTask;
}
I'm creating a download task as indicated in the AFNetworking docs (https://github.com/AFNetworking/AFNetworking#creating-a-download-task).
When the NSURLSessionDownloadTask reached the block completionHandler the error is null, so there's no error. Also, the filePath returns a valid NSURL, such as /var/mobile/Applications/id-of-the-app/Documents/section/section13.png.
The problem is that it's not saving the file in the specified folder (the folder exists, and the file to be downloaded too).
Any ideas? Here's the code:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:fileUrl]];
NSString *filename = [NSString stringWithFormat:#"section%#.%#", section.sectionId, [request.URL pathExtension]];
NSURL *saveUrl = [FilesManager urlForResourceType:ResourceTypeSection andFilename:filename];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request
progress:nil
destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
return saveUrl;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(#"path - %#", filePath);
if (!error) {
NSLog(#"we're good");
}
}];
[downloadTask resume];
I am using AFURLSessionManager to create a new download task:
AFURLSessionManager* manager = ...
NSProgress* p = nil;
NSURLSessionDownloadTask* downloadTask =
[manager downloadTaskWithRequest:request
progress:&p
destination:^NSURL*(NSURL* targetPath, NSURLResponse* response) {...}
completionHandler:^(NSURLResponse* response, NSURL* filePath, NSError* error) {...}
];
[downloadTask resume];
The file gets downloaded fine, however, how do I get progress notifications?
p is always set to nil. I've filed an issue for that.
I've also tried to call setDownloadTaskDidWriteDataBlock on the manager, and I do get progress notifications there but I receive them all grouped together after the file has been downloaded.
Seems like this area is still a bit buggy in AFNetworking 2.0
Any ideas?
You should observe the fractionCompleted property of your NSProgress object using KVO:
NSURL *url = [NSURL URLWithString:#"http://www.hfrmovies.com/TheHobbitDesolationOfSmaug48fps.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
// …
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
[progress removeObserver:self forKeyPath:#"fractionCompleted" context:NULL];
// …
}];
[downloadTask resume];
[progress addObserver:self
forKeyPath:#"fractionCompleted"
options:NSKeyValueObservingOptionNew
context:NULL];
Then add the observer method:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"fractionCompleted"]) {
NSProgress *progress = (NSProgress *)object;
NSLog(#"Progress… %f", progress.fractionCompleted);
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
Of course, you should check keyPath and/or object parameters to decide if that's the object/property you want to observe.
You can also use the setDownloadTaskDidWriteDataBlock: method from AFURLSessionManager (from which AFHTTPSessionManager inherits) to set a block for receiving download progress updates.
[session setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
NSLog(#"Progress… %lld", totalBytesWritten);
}];
This AFNetworking method maps the URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: method from NSURLSessionDownloadDelegate protocol to a more convenient block mechanism.
BTW, Apple's KVO implementation is severely broken. I recommend using a better implementation like the one proposed by Mike Ash with MAKVONotificationCenter. If you are interested in reading why Apple's KVO is broken, read Key-Value Observing Done Right by Mike Ash.
I faced a similar problem, and found a solution.
Check the link below:
http://cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html
#import <AFNetworking/UIKit+AFNetworking.h>
and use the additional method available to your UIProgressView
setProgressWithDownloadProgressOfTask:animated:
How I did it:
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error){
NSLog(#"File downloaded to: %#", filePath);
}];
[self.progressView setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];
Simple solutions for Swift:
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let sessionManager = AFURLSessionManager(sessionConfiguration: sessionConfiguration)
let request = NSURLRequest(URL: url)
let sessionDownloadTask = sessionManager.downloadTaskWithRequest(request, progress: nil, destination: { (url, response) -> NSURL in
return destinationPath.URLByAppendingPathComponent(fileName) //this is destinationPath for downloaded file
}, completionHandler: { response, url, error in
//do sth when it finishes
})
Now you have 2 options:
Using UIProgressView and setProgressWithDownloadProgressOfTask:
progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
Using AFURLSessionManager and setDownloadTaskDidWriteDataBlock:
sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
//do sth with current progress
}
At the end do not forget about:
sessionDownloadTask.resume()
For Download file with progress status use this code
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://..."];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress)
{
NSLog(#"Progress: %f", downloadProgress.fractionCompleted);
if (progressBlock) {
progressBlock(downloadProgress);
}
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
if (response && successBlock) {
successBlock(response,filePath);
}
NSLog(#"File downloaded to: %#", filePath);
}];
[downloadTask resume];