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

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];

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+;

How to prevent download with same request from AFHTTPRequestOperation?multiple download occurs for same file

I am using AFHTTPRequestOperation to download a file from remote server now my problem is AFHTTPRequestOperation starts to download same request multiple time so i want to prevent the download process to execute for same request.
so basically what i want is however if downloadFile: function call multiple time with same request i can prevent the download process to start if any process running with same request already.
following is my code
AFHTTPRequestOperation *operation;
-(void)downloadFile:(NSURL *)videoUrl{
NSURLRequest *request = [NSURLRequest requestWithURL:videoUrl];
operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:VIDEO_DIRECTORY_NAME];
NSString *downloadPath = [dataPath stringByAppendingPathComponent:[NSString stringWithFormat:#"TEMP_%#",[videoUrl lastPathComponent]]];
NSString *fullPath = [dataPath stringByAppendingPathComponent:[videoUrl lastPathComponent]];
// NSLog(#"Full Path For Download Video %#",fullPath);
NSError *error=[[NSError alloc]init];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath];
if (!fileExists)
{
NSLog(#"Full Path For Download Video Started%#",fullPath);
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:downloadPath append:NO]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
// NSLog(#"bytesRead: %lu, totalBytesRead: %lld, totalBytesExpectedToRead: %lld", (unsigned long)bytesRead, totalBytesRead, totalBytesExpectedToRead);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *error;
if (error) {
NSLog(#"ERR: %#", [error description]);
} else {
CustomAlertView *alert=[[CustomAlertView alloc]init];
NSUserDefaults *userDefaults=[NSUserDefaults standardUserDefaults];
//check for Available Space
if([ALDisk freeDiskSpaceInBytes] >= [operation.response expectedContentLength])
{
NSLog(#"Content-lent: %lld", [operation.response expectedContentLength]);
[alert ShowNotificationInParentView:nil WithTitle:NSLocalizedString(#"Video_title", nil) Message:NSLocalizedString(#"Video_downloaded_succesfully", nil) IsSuperUser:[userDefaults boolForKey:IS_SUPER_USER] TypeOfNotification:ALERT_TYPE_ERROR IsLoggedIn:YES];
[assetManager.assetManagerDelegate didAssetManagerSucceedObject:nil ErrorCode:#"" Result:YES ResponseId:VIDEO_DOWNLOAD_RESPONSE_ID];
}
else {
[alert ShowNotificationInParentView:nil WithTitle:#"Memory Full" Message:NSLocalizedString(#"video_cannot_be_downloaded", nil) IsSuperUser:[userDefaults boolForKey:IS_SUPER_USER] TypeOfNotification:ALERT_TYPE_ERROR IsLoggedIn:YES];
[assetManager.assetManagerDelegate didAssetManagerFailedResponseWithError:[NSError errorWithDomain:#"Memory Full" code:[MEMORY_OUT_OF_STORAGE intValue] userInfo:nil]];
}
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERR: %#", [error description]);
[assetManager.assetManagerDelegate didAssetManagerFailedResponseWithError:error];
}];
[operation start];
}
}
Please guide me with any suggestion or solution.

AFDownloadRequestOperation and ASIHTTPRequest not resuming Download

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.

File existence after AFNetworking download

I'm having some issues with finding my file after downloading it with AFNetworking...
The download itself goes fine, but when I check for the existence of the file afterwards, I can't find it... So I'm hoping someone can help me out...
In my code, I download the file, and in the completion block, I check for the existence (this is only done since I'm having issues finding it, it will be removed afterwards)...
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"url to file removed"]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"filename removed"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:#"filename removed" append:NO];
//Track the progress
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
{
if (totalBytesExpectedToRead > 0)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSString *progress = [NSString stringWithFormat:#"Downloaded %lld of %lld bytes",
totalBytesRead,
totalBytesExpectedToRead];
NSLog(#"%#", progress);
});
}
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"File downloaded to %#", path);
//Check for existence
NSFileManager *filemgr = [NSFileManager defaultManager];
if([filemgr fileExistsAtPath:path])
{
NSLog(#"File found");
} else
{
NSLog(#"File not found");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
[operation start];
Any ideas where it might be going wrong? As the download itself goes fine, the problem must lie with saving the file / the file system in iOS...
Does the directory you're trying to write to exist? If not you may find [NSOutputStream outputStreamToFileAtPath:#"filename removed" append:NO] is returning nil.
Try creating the directory first:
NSFileManager *fm = [NSFileManager defaultManager];
NSString *folder = [#"filename removed" stringByDeletingLastPathComponent];
if (![fm fileExistsAtPath:folder]) {
[fm createDirectoryAtPath:folder
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
I hope that helps.

Resources