AFDownloadRequestOperation and ASIHTTPRequest not resuming Download - ios

I am stuck in Resuming Download. I am using AFDownloadRequestOperation to download the file from Dropbox public link. Everything(Downloading and Resuming) was going fine. But suddenly i don't know what happened that Downloading is working fine but on App Restart Resuming is not working and each time giving "Request Timeout". While with link other then Dropbox(public link) Downloading and Resuming both are working fine. I have also tried same with ASIHTTPRequest and getting same behave. So What can the reason is there any problem with Dropbox public link? or is there any restriction with these library?
Please help i am much worried about my project's Progress. Project progress is stop due to this problem.
Here is my code
__weak typeof(self) weakSelf = self;
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:url.absoluteString.lastPathComponent];
operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.downloadQueue removeObject:url.absoluteString];
[weakSelf checkDownloadQueueForMoreDownload];
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setProgressiveDownloadProgressBlock:^(AFDownloadRequestOperation *operation, NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
if (totalBytesExpected != totalBytesExpectedToReadForFile &&( weakSelf.isDefaultProgressSet == NO)) {
long long bytesHasWritten = totalBytesExpectedToReadForFile-totalBytesExpected;
[weakSelf.delegate downloadedNumberOfBytes:((float)bytesHasWritten/
(float)totalBytesExpectedToReadForFile)
forAnnotaionView:annotView];
weakSelf.isDefaultProgressSet = YES;
}
NSLog(#"Operation%i: bytesRead: %d", 1, bytesRead);
NSLog(#"Operation%i: totalBytesRead: %lld", 1, totalBytesRead);
NSLog(#"Operation%i: totalBytesExpected: %lld", 1, totalBytesExpected);
NSLog(#"Operation%i: totalBytesReadForFile: %lld", 1, totalBytesReadForFile);
NSLog(#"Operation%i: totalBytesExpectedToReadForFile: %lld", 1, totalBytesExpectedToReadForFile);
float progress = ((float)totalBytesReadForFile/(float)totalBytesExpectedToReadForFile);
[weakSelf.delegate downloadedNumberOfBytes:progress forAnnotaionView:annotView];
}];
[operation start];
On resuming always going to Failure block.

Related

Is it necessary to manually clear the Incomplete folder generated by AFNetworking? [duplicate]

This question already has answers here:
iPhone storage in tmp directory
(2 answers)
Closed 7 years ago.
As title, I am handling a case that when downloading a large zip file using AFNetworking 2.5.4 framework, the user quit the app accidentally. I would like to know if it is necessary to manually clear the Incomplete folder (<app_name>/tmp/Incomplete) generated by AFNetworking, as the zip file downloading is quite large. Will iOS handle this folder if it find the folder size if growing?
P.S. My downloading logic is by using NSOperationQueue and the below AFDownloadRequestOperation:
- (AFDownloadRequestOperation *)operation
{
if (_operation) {
return _operation;
}
_operation = [[AFDownloadRequestOperation alloc] initWithRequest:self.downloadRequest
targetPath:self.targetPath
shouldResume:YES];
#ifdef DEBUG
_operation.securityPolicy.allowInvalidCertificates = YES;
#endif
[_operation setProgressiveDownloadProgressBlock:self.progressBlock];
[_operation setCompletionBlockWithSuccess:self.completionBlock
failure:self.failureBlock];
_operation.deleteTempFileOnCancel = YES;
return _operation;
}
you can resume the incomplete download with this
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"....zip"]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"....zip"];
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setProgressiveDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
NSLog(#"Operation%i: bytesRead: %d", 1, bytesRead);
NSLog(#"Operation%i: totalBytesRead: %lld", 1, totalBytesRead);
NSLog(#"Operation%i: totalBytesExpected: %lld", 1, totalBytesExpected);
NSLog(#"Operation%i: totalBytesReadForFile: %lld", 1, totalBytesReadForFile);
NSLog(#"Operation%i: totalBytesExpectedToReadForFile: %lld", 1, totalBytesExpectedToReadForFile);
}];
[operations addObject:operation];
OR you can delete temp files
+ (void)clearTmpDirectory
{
NSArray* tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
for (NSString *file in tmpDirectory) {
[[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:#"%#%#", NSTemporaryDirectory(), file] error:NULL];
}
}

AFNetworking: download + resume big file?

I'm using AFNetworking to download a big file. Here is my code. It work fine:
- (AFDownloadRequestOperation*)downloadBigFile:(BigFileObject*)bigFile
withCompleteBlock:(AFResultCompleteBlock)completeBlock
errorBlock:(AFResultErrorBlock)errorBlock{
NSString *name = [NSString stringWithFormat:#"%#", bigFile.name];
NSString *link = [NSString stringWithFormat:#"%#", bigFile.link];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:link]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mp4", name]];
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
completeBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
errorBlock(error);
}];
[operation setProgressiveDownloadProgressBlock:^(AFDownloadRequestOperation *operation, NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
float progress = (float)totalBytesReadForFile / totalBytesExpectedToReadForFile;
//block
self.progressBlock(progress, totalBytesReadForFile, totalBytesExpectedToReadForFile);
}];
[operation start];
return operation;
}
A file is being downloaded to local but not finished, take 30% finished for an example. Then stop it. Few day late, I resume it, but that link was not live. So, I request a new link and I wanna download from 30%. How to do it?
My app is target iOS 6+;

Memory pressure issue while downloading multiple files using AFNetworking

In my application i am trying to download thousands of images (each image size with a maximum of 3mb) and 10's of videos (each video size with a maximum of 100mb) and saving it in Documents Directory.
To achieve this i am using AFNetworking
Here my problem is i am getting all the data successfully when i am using a slow wifi (around 4mbps), but the same downloading if i am doing under a wifi with a speed of 100mbps the application is getting memory warning while downloading images and memory pressure issue while downloading videos and then application is crashing.
-(void) AddVideoIntoDocument :(NSString *)name :(NSString *)urlAddress{
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlAddress]];
[theRequest setTimeoutInterval:1000.0];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:name];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
//NSLog(#"Download = %f", (float)totalBytesRead / totalBytesExpectedToRead);
}];
[operation start];
}
-(void)downloadRequestedImage : (NSString *)imageURL :(NSInteger) type :(NSString *)imgName{
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:imageURL]];
[theRequest setTimeoutInterval:10000.0];
AFHTTPRequestOperation *posterOperation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
posterOperation.responseSerializer = [AFImageResponseSerializer serializer];
[posterOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//NSLog(#"Response: %#", responseObject);
UIImage *secImg = responseObject;
if(type == 1) { // Delete the image from DB
[self removeImage:imgName];
}
[self AddImageIntoDocument:secImg :imgName];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Image request failed with error: %#", error);
}];
[posterOperation start];
}
The above code i am looping according to the number of videos and images that i have to download
What is the reason behind that behaviour
I even have screen shots of memory allocation for both the scenarios
Please Help
Adding code for saving the downloaded images also
-(void)AddImageIntoDocument :(UIImage *)img :(NSString *)str{
if(img) {
NSData *pngData = UIImageJPEGRepresentation(img, 0.4);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePathName =[[paths objectAtIndex:0]stringByAppendingPathComponent:str];
[pngData writeToFile:filePathName atomically:YES];
}
else {
NSLog(#"Network Error while downloading the image!!! Please try again.");
}
}
The reason for this behavior is that you're loading your large files into memory (and presumably it's happening quickly enough that you app isn't having a chance to respond to memory pressure notifications).
You can mitigate this by controlling the peak memory usage by not loading these downloads into memory. When download large files, it's often better to stream them directly to persistent storage. To do this with AFNetworking, you can set the outputStream of the AFURLConnectionOperation, and it should stream the contents directly to that file, e.g.
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path = [documentsPath stringByAppendingPathComponent:[url lastPathComponent]]; // use whatever path is appropriate for your app
operation.outputStream = [[NSOutputStream alloc] initToFileAtPath:path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"successful");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failure: %#", error);
}];
[self.downloadQueue addOperation:operation];
BTW, you'll notice that I'm not just calling start on these requests. Personally, I always add them to a queue for which I've specified the maximum number of concurrent operations:
self.downloadQueue = [[NSOperationQueue alloc] init];
self.downloadQueue.maxConcurrentOperationCount = 4;
self.downloadQueue.name = #"com.domain.app.downloadQueue";
I think this is less critical regarding memory usage than the streaming of the results directly to a outputStream using persistent storage, but I find this is another mechanism for managing system resources when initiating many concurrent requests.
You can start using NSURLSession's downloadTask.
I think this will resolve your issue.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://someSite.com/somefile.zip"]];
[[NSURLSession sharedSession] downloadTaskWithRequest:request
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
{
// Use location (it's file URL in your system)
}];

Downloading concurrent song files

I am Very new to iOS Application Development Platform, I am searching for one thing from Last Few weeks, actually my requirement is I have a UITableview with few Urls,and On didselectRowAtIndexPath That song should run in the Background and it downloading progress shows in another tab.
When I clicked multiple Buttons then multiple songs are downloaded simultaneously and all downloading progress should shown individually in the next Tab and here I have felicity to Pause, resume, and cancel the particular download. this is my requirement. I use AFNetworking But it is not Clear Please Help me and do the needful.
my AFNetworking code below
NSURL *url = [NSURL URLWithString:downLoadedUrlParam];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3600];
NSString *MUSICFile=[DocumentsDirectory stringByAppendingPathComponent:songName];
self.operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:MUSICFile shouldResume:YES];
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", MUSICFile);
//[ProcessingUrlsArray removeObject:videoString];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
if(operation.response.statusCode!= 200) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Alert" message:#"Error While Downloaded" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}];
[httpClient enqueueHTTPRequestOperation:self.operation];
[self.operation setProgressiveDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
float percentDone = totalBytesReadForFile/(float)totalBytesExpectedToReadForFile;
NSLog(#"------%#",[NSString stringWithFormat:#"CUR : %lli M",totalBytesReadForFile/1024/1024]);
NSLog(#"------%#",[NSString stringWithFormat:#"TOTAL : %lli M",totalBytesExpectedToReadForFile/1024/1024]);
NSLog(#"------%f",percentDone);
NSLog(#"------%.0f%%",percentDone*100);
self.myProgressBar.progress=percentDone;
NSLog(#"Operation%i: bytesRead: %d", 1, bytesRead);
NSLog(#"Operation%i: totalBytesRead: %lld", 1, totalBytesRead);
NSLog(#"Operation%i: totalBytesExpected: %lld", 1, totalBytesExpected);
NSLog(#"Operation%i: totalBytesReadForFile: %lld", 1, totalBytesReadForFile);
NSLog(#"Operation%i: totalBytesExpectedToReadForFile: %lld", 1, totalBytesExpectedToReadForFile);
NSLog(#"%#",downLoadedUrlParam);
self.title=downLoadNameParam;
NSMutableArray *stgPerst;
stgPerst=[[NSMutableArray alloc]initWithCapacity:0];
NSDictionary *dicInfo=[NSDictionary dictionaryWithObjects:#[[NSString stringWithFormat:#"%f",percentDone],downLoadNameParam] forKeys:#[#"heProg",#"heName"]];
NSLog(#"dict=%#",dicInfo);
[[NSNotificationCenter defaultCenter] postNotificationName:#"DOWNLOAD_PROGRESS" object:nil userInfo:dicInfo];
}];

Using append:YES with operation.outputStream AFHTTPRequestOperation doesn't work

I am trying to download a text file and if this download is paused I am trying to append the rest of the file.
The problem is that i am starting to download the rest from the right point but the file is not appending it overrides the previous file.
Here is my source code:
+ (void) downloadFile:(NSManagedObject *)file {
NSString *url = [file valueForKey:#"path"];
NSString *fileName = [[file valueForKey:#"path"] lastPathComponent]; // TODO chnage to file ID (it will be good to add id before file name)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
BOOL append = NO;
unsigned long long size = 0;
BOOL resumeOperation = NO;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
resumeOperation = YES;
NSError *error = nil;
NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];
size = [[dict objectForKey:NSFileSize] longLongValue];
if (!error) {
error = nil;
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
if (error) {
NSLog(#"Error removing old file: %#", [error localizedDescription]);
}
NSString *val = [NSString stringWithFormat:#"bytes=%lld-", size];
append = YES;
[request setValue:val forHTTPHeaderField:#"Range"];
}
}
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request] ;
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:YES];
//gives more 10 minuts when the app is minimmized
[operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
[operation pause];
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
totalBytesRead += size;
float percent = ((float)totalBytesRead) / (totalBytesExpectedToRead + size);
// TODO update database with bytes amount
NSLog(#"%.2f%% - [%d]", percent * 100, [[CoreDataManager getQueue] count]);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"File downloaded succesffully!");
[self reportEndDownload:file withStatusCode:[NSNumber numberWithInt:DOWNLAOD_STATUS_COMPLETE]];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// NSLog(#"Error while downloading file: %#", [error localizedDescription]);
// ? ask about server corrupted files - here is a loop -----> Itay OK
[self reportEndDownload:file withStatusCode:[NSNumber numberWithInt:DOWNLOAF_STATUS_CONNECTION_ERROR]];
}];
if (resumeOperation ) {
[operation resume];
}else{
[operation start];
}
}
You can use AFDownloadRequestOperation to do this.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"....zip"]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"....zip"];
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setProgressiveDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
NSLog(#"Operation%i: bytesRead: %d", 1, bytesRead);
NSLog(#"Operation%i: totalBytesRead: %lld", 1, totalBytesRead);
NSLog(#"Operation%i: totalBytesExpected: %lld", 1, totalBytesExpected);
NSLog(#"Operation%i: totalBytesReadForFile: %lld", 1, totalBytesReadForFile);
NSLog(#"Operation%i: totalBytesExpectedToReadForFile: %lld", 1, totalBytesExpectedToReadForFile);
}];
[operations addObject:operation];

Resources