I am trying to download a file using AFNetworking and the download gets redirected to Amazons Web Services. I can see the redirect but it never seems to pick up the download so I was wondering what I'm doing wrong! Here's my code:
NSString *urlString = [[NSString alloc]initWithFormat:#"%#?%#=%#", update.downloadUrl.absoluteString, #"auth_token", database.userAuthToken];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
NSLog(#"Response: %#", redirectResponse.debugDescription);
NSLog(#"Request: %#", request.debugDescription);
if(redirectResponse == nil) return request;
NSMutableURLRequest *urlRequest = [httpClient requestWithMethod:#"GET" path:request.URL.absoluteString parameters:nil];
return urlRequest;
}];
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:[item.downloadUrl absoluteString] append:false]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
[_currentItem setUpdateProgress:totalBytesRead / (float)totalBytesExpectedToRead];
NSLog(#"BytesRead: %i, TotalBytesRead: %lld, BytesToRead: %lld", bytesRead, totalBytesRead, totalBytesExpectedToRead);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
[self networkQueueComplete:operation withResponse:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self networkQueueFailed:operation withError:error];
}];
[networkQueue addOperation:operation];
In the setRedirectResponse block I can see the right redirect url, but my setDownloadProgress block never gets called.
I add a redirect page on my server,and run your code. I found that if return request directly in setRedirectResponseBlock:, the redirect download work well,setDownloadProgress block gets called.
[operation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
NSLog(#"Response: %#", redirectResponse.debugDescription);
NSLog(#"Request: %#", request.debugDescription);
return request;
}];
UPDATE:
My test redirect page:http://joiningsstest.byethost11.com/redirect.php
you can pass your redirect url with "url" parameter in http/get.
I’m not sure if your s3 url need authorize for access.In my test code,i used "http://still.s3.amazonaws.com/Material/Chimney/images/1.jpg" for redirect,this is a public s3 url.
Redirect page's code:
<?php
if($_GET['url'])
{
header('HTTP/1.1 302 Moved Permanently');
header('Location:'.$_GET['url']);
}
?>
My test code:
NSString * redirectURL = #"http://still.s3.amazonaws.com/Material/Chimney/images/1.jpg";
NSString * testURL = [NSString stringWithFormat:#"http://joiningsstest.byethost11.com/redirect.php?url=%#",redirectURL];
NSURLRequest * originalRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:testURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:originalRequest];
[operation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
NSLog(#"Response: %#", redirectResponse.debugDescription);
NSLog(#"Request: %#", request.debugDescription);
return request;
}];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"1.jpg"];
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:path append:false]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"BytesRead: %i, TotalBytesRead: %lld, BytesToRead: %lld", bytesRead, totalBytesRead, totalBytesExpectedToRead);
}];
[operation start];
Related
When I use AFNetworking 2, I could get progress with AFHTTPRequestOperation like this:
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:aURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:_timeoutInterval];
AFHTTPRequestOperation *imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
imageRequestOperation.responseSerializer = [AFImageResponseSerializer serializer];
__weak AFHTTPRequestOperation *imageRequestOperationForBlock = imageRequestOperation;
[imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// ...
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// ...
}];
[imageRequestOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
if (progress) {
progress((float)totalBytesRead / totalBytesExpectedToRead);
}
}];
I use AFHTTPSessionManager GET:parameters:success:failure: to get data, but I don't know how to get download progress in AFNetworking 3.0.
Link in comments was missleading (NSURLSessionDownloadTask). Sorry about that.
Code below should work though.
Assumption: this code is placed in AFHTTPSessionManager subclass with an NSURLSessionDataTask *testTask ivar declared. It should be easy enough modify as needed.
Vital part of code taken from this answer
- (void)test
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://eoimages.gsfc.nasa.gov/images/imagerecords/78000/78797/nwpassage_tmo_2012199_lrg.jpg"]];
testTask = [self dataTaskWithRequest:request
completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error)
{
//...
NSLog(#"error");
}
else
{
//...
UIImage *result = responseObject;
NSLog(#"Success: %#",NSStringFromCGSize(result.size));
}
}];
[self setDataTaskDidReceiveDataBlock:^(NSURLSession *session,
NSURLSessionDataTask *dataTask,
NSData *data)
{
if (dataTask.countOfBytesExpectedToReceive == NSURLSessionTransferSizeUnknown)
return;
if (dataTask != testTask)
return;
NSUInteger code = [(NSHTTPURLResponse *)dataTask.response statusCode];
if (!(code> 199 && code < 400))
return;
long long bytesReceived = [dataTask countOfBytesReceived];
long long bytesTotal = [dataTask countOfBytesExpectedToReceive];
NSLog(#"... %lld/%lld",
bytesReceived,
bytesTotal);
}];
[testTask resume];
}
im using AFNetworking 2, how to set setWillSendRequestForAuthenticationChallengeBlock for sending a certificate on challenge?
NSString *url = [NSString stringWithFormat:#"%#%#", API_URL_ROOTV1, API_URL_HUBA];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"GET"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[operation start];
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_
in the file where I tried to call setWillSendRequestForAuthenticationChallengeBlock:
I understood that cocoapods already did the #define in Pods-prefix.pch and did not expect that it should be defined again.
it may help u..
I having problem with downloading array of images from server, if i have 100 images on server means i should download all images using "AFImageRequestOperation", while downloading process some images are downloaded successfully but many images are failed to download because of "TimeOut" error from server,i facing Timeout issue with large size image(3.mb),
i using follwing way to downloading images:
NSURL *url = [NSURL URLWithString:kBaseURLString];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setAuthorizationHeaderWithUsername:[[NSUserDefaults standardUserDefaults] stringForKey:kUserDefaultKeyUsername]
password:[[NSUserDefaults standardUserDefaults] stringForKey:kUserDefaultKeyPassword]];
for( int i = 0; i < [self.downloadImageList count]; i++ ) {
NSString *filename = [[NSString alloc] initWithString:[self.downloadImageList objectAtIndex:i]];
NSMutableURLRequest *urlRequest = [httpClient multipartFormRequestWithMethod:#"POST"
path:#"/xxx/yyyyyyyyyy/getImage"
parameters:nil
constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFormData:[filename dataUsingEncoding:NSUTF8StringEncoding]
name:kFormNameFile];
}];
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
[requestOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
[self updateSyncClientUIDelegateProgress:(totalBytesRead/totalBytesExpectedToRead) andLabel:#"Downloading Images"];
}];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if( [[urlRequest URL] isEqual:[[operation request] URL]] ) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = responseObject;
NSLog(#"Downloading image %#",image);
[UIImagePNGRepresentation(image) writeToFile:[syncedImagesPath stringByAppendingPathComponent:filename] atomically:YES];
});
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if( [[operation response] statusCode] == 404 ) {
return;
}
NSLog(#"failure BLOCK %#",error);
NSLog(#"failure error code %ld",(long)[error code]);
if( [error code] != NSURLErrorCannotDecodeContentData ) {
[self cancelSyncFromFailure];
}
}];
Please help me to fix this timeout issue while downloading large iamges
NOW HERE IS THE SOLUTION I AM USING AND WORKING FINE.FIRSTLY IT WAS ALSO SENDING ME THE "REQUEST TIMEOUT" MESSAGE BUT NOT NOW.TRY THIS
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photourl] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:10000];
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
[requestOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
...... YOUR CODE
}];
You set TimeOut Request Time is more a below code.
[urlRequest setTimeoutInterval:50];
I create one application that has one page and in this page exist one button that downloaded file when click on.
I can download file with AFNetworking but in my has error ....
this is my code :
- (IBAction)downloads:(id)sender
{
NSLog(#"start downloads");
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:
#"http://.../500x333xgalaxy-core-product-image-1tn.jpg,
q1367836642.pagespeed.ic.eafBYU8jUN.jpg"]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent
:#"filename.jpg"];
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);
}];
}
this error is :
No visible #interface 'AFURLConnectionOpretion' declares the selector
'setCompletionBlockWithSuccess'
Use the following line to start the operation :
[operation start];
Here is my download code
AFHTTPRequestOperation *urlConnection;
urlConnection = [[AFHTTPRequestOperation alloc] initWithRequest:request];
urlConnection.outputStream = [NSOutputStream outputStreamToFileAtPath:outputPath append:NO];
[urlConnection setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Download Completed");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error occured while downloading");
}];
[urlConnection setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
}];
change "AFURLConnectionOperation *operation" to "AFHTTPRequestOperation *operation"
i think thats the issue
I'm trying to compile application on my iPad. I'm using AFNetworking to get list of files on my FTP. Application works on simulator, but when i start it on iPad i get (null) content of file with list. Here's code:
- (void) getListOfFiles {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"ftp://anonymous#ftphost/"]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"list"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, NSHTTPURLResponse *response) {
NSLog(#"Success %#",operation.response);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error localizedDescription]);
}];
[operation start];
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSLog (#"%#",content);
}
So variable content = (null) only on iPad, and on Simulator everything is fine. Please help, i have lost any hope )
the AFHTTP*Operations are all asynchronous by default.
this is proper, since synchronous(blocking) calls block the main thread
you are starting the operation and take file content directly afterwards. This can't work reliably because the start call is ASYNC and only STARTS the op but doesnt wait for it
either wait for it ... which is BAD as it blocks the thread:
[operation start];
[operation waitUntilDone];
or MUCH BETTER modify getFiles to work asynchronously:
- (void) getListOfFiles {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"URL"]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"list"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, NSHTTPURLResponse *response) {
NSLog(#"Success %#",operation.response);
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSLog (#"%#",content);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error localizedDescription]);
}];
[operation start];
}
Ok, problem solved. I can't write to bundle directory, so i nee to use next code instead:
NSArray *paths = NSSearchPathForDirectoiesDomain(NSDocumentDirectory,NSCachesDirectory,YES);
NSString *path = [[paths objectAtIndex:0] stingByAppendingPathComponent:#"list"];