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];
Related
I'm trying to migrate this code over to AFNetworking 3.1 but I'm having some issues with the HTTPRequestOperationWithRequest function. From what I can tell it's been deprecated but I don't know what to use instead.
Here is the code:
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
timeoutInterval:(NSTimeInterval)timeoutInterval
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
[request setTimeoutInterval:timeoutInterval];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
As you can see in the README AFNetworking has switched to NSURLSession. This means that to create a request you do something like this:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil 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) {
NSLog(#"File downloaded to: %#", filePath);
}];
[downloadTask resume];
Your exact function can't be replicated but you can probably work your way back to the caller of that function and replace it with something similar.
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];
}
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];
}
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 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];