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.
Related
I am trying to download .xlsx file from server using AFNetworking. But it gives me error saying:
Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: application/zip" UserInfo={NSLocalizedDescription=Request failed: unacceptable content-type: application/zip
It shows whole response inside the NSError.
I don't want to use any third party library as I am integrating this in my SDK itself.
To Download .xlsx file in AFNetworking2.x. You can't use this code. This code is for Json Serialization.
Reason:
/*
In AFURLResponseSerialization.m this line will convert downloaded data to json, which make invalid serialization error
*/
responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
NOT Working Code :
// This code will not work for XLSX File
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", #"text/html", nil];
[manager GET:#"Link to xlsx File" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Use this :
https://github.com/AFNetworking/AFNetworking/tree/2.x#creating-a-download-task
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"Link to xlsx File"];
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];
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];
}
How to post a image using AFNetworking.i am using below code to post an image.but image is not uploading to server.After posting image i am getting this link in result "http://thisisswitch.com:8084/SmartSwitchService/UserImages/69684177-4601-4665-8890-5424e3fbff73.png".
Can anyone tell me what the problem in code ?
Here is my Code:
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:BaseUrl]];
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:posturl parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFormData:imgData name:#"image"];
}];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSDictionary *dict = (NSDictionary *)JSON;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
From the Github read me:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:#"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"Success: %# %#", response, responseObject);
}
}];
[uploadTask resume];
Here's how I'm doing it (in AFNetworking 2.x):
- (void)requestWithFormData:(void (^)(id <AFMultipartFormData> formData))formBlock
withParams:(NSDictionary *)params
webservicePath:(NSString *)webservicePath
success:(void (^)(AFHTTPRequestOperation *operation, id jsonDictionary))successBlock
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock
{
// Handle request for file upload
AFHTTPRequestOperation *op = [self.manager POST:webservicePath
parameters:params
constructingBodyWithBlock:formBlock
success:success
failure:failureBlock];
[op start];
}
Then I use it as per the following:
void (^formBlock)(id <AFMultipartFormData> formData) = ^(id <AFMultipartFormData>formData)
{
NSData *data1 = UIImagePNGRepresentation(profileImage);
[formData appendPartWithFileData:data1 name:#"file" fileName:#"picture.png" mimeType:#"image/png"];
};
[networkingUtil requestWithFormData:formBlock
withParams:params
webservicePath:#"myserver.com/upload"
success:successBlock
failure:failureBlock];
Your server should handle the form data and look for file.
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 the AFNetworking library. I can't figure out how to download a file and save it to the documents directory.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"..."]];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"filename"];
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 start];
I'm gonna bounce off #mattt's answer and post a version for AFNetworking 2.0 using AFHTTPRequestOperationManager.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"filename"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *op = [manager GET:#"http://example.com/file/to/download"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"successful download to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
op.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
I'm talking about AFNetworking 2.0
[AFHTTPRequestOperationManager manager] creates manager object with default AFJSONResponseSerializer, and it performs content types restriction. Take a look at this
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
data:(NSData *)data
error:(NSError * __autoreleasing *)error
So we need to create a none response serializer and use AFHTTPRequestOperationManager as normal.
Here is the AFNoneResponseSerializer
#interface AFNoneResponseSerializer : AFHTTPResponseSerializer
+ (instancetype)serializer;
#end
#implementation AFNoneResponseSerializer
#pragma mark - Initialization
+ (instancetype)serializer
{
return [[self alloc] init];
}
- (instancetype)init
{
self = [super init];
return self;
}
#pragma mark - AFURLResponseSerializer
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
{
return data;
}
#end
Usage
self.manager = [AFHTTPRequestOperationManager manager];
self.manager.responseSerializer = [AFNoneResponseSerializer serializer];
[self.manager GET:#"https://sites.google.com/site/iphonesdktutorials/xml/Books.xml"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) {
failure(error);
}
}];
so that we can get the whole file without any serialization
Documentation page has example with section 'Creating a Download Task':
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];
NB! Code work with iOS 7+ (tested with AFNetworking 2.5.1)
From AFNetworking docs.
Save to loaded file to your documents.
AFNetworking 3.0
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];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFCompoundResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/octet-stream"];
AFHTTPRequestOperation *operation = [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (responseObject) {
// your code here
} else {
// your code here
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[operation start];
// manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject: #"application/octet-stream"]; can vary depending on what you expect
Yes, it is better to use AFNetworking 2.0 way with AFHTTPRequestOperationManager. With old way my file did download but for some reason didn't update in file system.
Appending to swilliam's answer, to show download progress, in AFNetworking 2.0 you do similarly - just set download progress block after setting output stream.
__weak SettingsTableViewController *weakSelf = self;
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:newFilePath append:NO];
[operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToRead) {
float progress = totalBytesWritten / (float)totalBytesExpectedToRead;
NSString *progressMessage = [NSString stringWithFormat:#"%# \n %.2f %% \n %# / %#", #"Downloading ...", progress * 100, [weakSelf fileSizeStringWithSize:totalBytesWritten], [weakSelf fileSizeStringWithSize:totalBytesExpectedToRead]];
[SVProgressHUD showProgress:progress status:progressMessage];
}];
This is my method to create bytes string:
- (NSString *)fileSizeStringWithSize:(long long)size
{
NSString *sizeString;
CGFloat f;
if (size < 1024) {
sizeString = [NSString stringWithFormat:#"%d %#", (int)size, #"bytes"];
}
else if ((size >= 1024)&&(size < (1024*1024))) {
f = size / 1024.0f;
sizeString = [NSString stringWithFormat:#"%.0f %#", f, #"Kb"];
}
else if (size >= (1024*1024)) {
f = size / (1024.0f*1024.0f);
sizeString = [NSString stringWithFormat:#"%.0f %#", f, #"Mb"];
}
return sizeString;
}
In addition to the previous answers, with AFNetworking 2.5.0 and iOS7/8 I have found that that the extra step of opening the output stream is also needed to prevent the app from hanging (and eventually crashing from lack of memory).
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:dest
append:NO];
[operation.outputStream open];
[operation start];