AFNetworking file upload - ios

I'm trying to upload file with AFNetworking and it is working with iOS Simulator but not working Real devices, i tried 2 different way but same.
Can some one help me to solve this issue please
Thank you very much.
this is first code
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *dir = [paths objectAtIndex:0];
NSString *mp3File = [dir stringByAppendingPathComponent:#"Mp3File.mp3"];
NSData* myData = [mp3File dataUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"nid": nid, #"uid": [NSString stringWithFormat:#"%#", [appSet objectForKey:#"userid"]]};
AFHTTPRequestOperation *op = [manager POST:#"http://192.168.1.103/sample_Files/mp3.php" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:myData name:#"userfile" fileName:[NSString stringWithFormat:#"%#.mp3", dateString] mimeType:#"audio/mpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"YESSS UPLOADED");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error);
}];
[op start];
and this is other one
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"nid": nid, #"uid": [NSString stringWithFormat:#"%#", [appSet objectForKey:#"userid"]]};
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"Mp3File.mp3"];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
AFHTTPRequestOperation *op = [manager POST:#"http://192.168.1.103/sample_Files/mp3.php" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSError *error;
BOOL success = [formData appendPartWithFileURL:fileURL name:#"userfile" fileName:[NSString stringWithFormat:#"%#.mp3", dateString] mimeType:#"audio/mpeg" error:&error];
if (!success)
NSLog(#"appendPartWithFileURL error: %#", error);
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[op start];

From what I've seen it looks correct.
Have you set a breakpoint on the FAILURE to see what the NSERROR response is?
Here's a sample URL that posted a very similar solution.
Uploading image with AFNetworking 2.0

Related

How to send image as parameters (param) with POST with AFNetworking

I need to send image as param like
URl : some API
params : {profileImage:string(file)}
Means in param list only i have to send image file as string.
i used the below code. but it is not working.
NSData *dataImage = [[NSData alloc] init];
dataImage = UIImagePNGRepresentation(selectedImage);
NSString *stringImage = [dataImage base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSDictionary *params = {profileImage : stringImage}
NSString *url = [NetworkRoutes postProfileImageAPIWithMobileNumber:[PTUserDetails getMobileNumber]];
self.operationManager = [AFHTTPSessionManager manager];
self.operationManager.responseSerializer = [AFJSONResponseSerializer serializer]; //
[self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:#“userName” password:#“some password”];
[self.operationManager POST:url parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSError *error;
if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:#"file" fileName:[path lastPathComponent] mimeType:#"image/jpg" error:&error]) {
NSLog(#"error appending part: %#", error);
}
} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
your answer no need to be in afnetworking , can also be in nsurlconnection
I am getting resposne
{
response :"Please upload image file"
}
OR
Suggest me how to do like in the attached screen shot . In post man i am getting response
NSData *imgData = UIImageJPEGRepresentation(image, 1.0);
NSUInteger fileSize = [imgData length];
if(fileSize>400000)
{
float size = (float)((float)400000/(float)fileSize);
imgData = [NSData dataWithData:UIImageJPEGRepresentation(image, size)];
}
NSString *imgProfilePic = [imgData base64Encoding];
and then you can send this imgProfilePic to Webservice
If you send your image in multipart then this might be helpful and easiest way than BASE64
and also no need to convert your image into BASE64 String.
- (void)uploadImage:(UIImage*)image withParams:(NSDictionary*)paramsDict withURL:(NSString *)URL
{
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
AFHTTPRequestOperationManager *manager =
[AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager POST:URL parameters:paramsDict constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if (imageData!=nil) {
[formData appendPartWithFileData:imageData name:#"imagename" fileName:#"filename" mimeType:#"image/jpeg"];
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success = %#", responseObject);
[appDelegate dismissLoading];
if ([[responseObject valueForKey:#"code"] isEqualToString:#"200"])
{
// code after success
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[appDelegate dismissLoading];
NSLog(#"error = %#", error);
}];
}
Try to send like following (one of the below) way:
1.
-(void)uploadimage{
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"http://your server.url"]];
NSData *imageData = UIImageJPEGRepresentation(self.avatarView.image, 0.5);
// if you want to pass another parameter with image then
NSDictionary *param = #{#"username": self.username, #"password" : self.password};
AFHTTPRequestOperation *operation = [manager POST:#"rest.of.url" parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//do not put image inside parameters dictionary, but append it!
[formData appendPartWithFileData:imageData name:paramNameForImage fileName:#"photo.jpg" mimeType:#"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[operation start];
}
2.
UIImage *image = [UIImage imageNamed:#"imageName.png"];
NSData *imageData = UIImageJPEGRepresentation(image,1);
NSString *queryStringss = [NSString stringWithFormat:#"http://your server/uploadfile/"];
queryStringss = [queryStringss stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[manager POST:queryStringss parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileData:imageData name:#"fileName" fileName:#"imageName.png" mimeType:#"image/jpeg"];
}
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *dict = [responseObject objectForKey:#"Result"];
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];

AFNetworking form data uploading issue

I want to POST form data using AFNetworking. I am using this piece of code to achieve this:
// Create service request url
NSString *urlString = [NSString stringWithFormat:#"%#%#", kBaseURL, webServiceAPIName];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:#"myUser" forHTTPHeaderField:#"X-User-Agent"];
[manager.requestSerializer setValue:#"multipart/form-data" forHTTPHeaderField:#"Content-Type"];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// Set calling keys
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"5341" forKey:#"Id"];
[dict setObject:#"f1" forKey:#"refDataId"];
[dict setObject:#"f1" forKey:#"customRefDataId"];
[dict setObject:#"587" forKey:#"cost"];
[manager POST:urlString parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImagePNGRepresentation(files[0]) name:#"ImageName" fileName:#"file1" mimeType:#"image/png"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"upload successful");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error image upload");
}];
After execution of this block after waiting some time it goes in Failure Section. Logging : "Error image upload". without giving any error.
I tried my API in POSTMAN API CLIENT and there it is working fine.I am able to send data and get response back.
And after running this block i am not able to run any other API call I have to stop my app and run again to run any other API call.
What is the issue with this code why I am not able to upload any form data and Why it block my any other API calls
Try below code:
-(void) uploadImage {
NSString *imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:#"userimage"];
NSString * urlString = [stagingURL stringByReplacingOccurrencesOfString:#"user/" withString:#""];
NSString * uploadURL = #"Your URL where image to be uploaded";
NSLog(#"uploadImageURL: %#", uploadURL);
NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]], 0.5);
NSString *queryStringss = [NSString stringWithFormat:#"%#",uploadURL];
queryStringss = [queryStringss stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer=[AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/plain"];
[manager POST:queryStringss parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"file" fileName:#"file" mimeType:#"image/jpeg"];
}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];}

How to add header in Multipart Form data request iOS?

Following is my code snippet. I am getting an error while runnning this code. I have added headers as part of the request. Is that the correct way ?
__block int i=1;
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:url]];
NSDictionary *parameters = #{#"wave_Id": [inputDictionary objectForKey:#"wave_Id"]};
AFHTTPRequestOperation *op = [manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
for(NSData *imageData in [inputDictionary objectForKey:#"images"])
{
[formData appendPartWithFileData:imageData name:[NSString stringWithFormat:#"file%d",i] fileName:[NSString stringWithFormat:#"abc%d.png",i] mimeType:#"image/png"];
i++;
}
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error];
NSAssert(jsonData, #"Failure building JSON: %#", error);
NSLog(#"Json Data Image Upload %#",jsonData);
NSAssert(jsonData, #"Failure building JSON: %#", error);
NSString *token = [SSKeychain passwordForService:RegistrationTokenKey account:LoggedInUserKey];
NSDictionary *jsonHeaders = #{#"Content-Disposition" : #"form-data; name=\"parameters\"",
#"Content-Type" : #"application/json",
#"Accept" : #"application/json",
#"Authorization" : token};
[formData appendPartWithHeaders:jsonHeaders body:jsonData];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[op start];
I need your complete method to be 100% sure, but please try writing this way and see if it helps:
__block int i = 1;
NSMutableArray *mutableOperations = [NSMutableArray array];
NSDictionary *parameters = #{#"wave_Id": [inputDictionary objectForKey:#"wave_Id"]};
for (NSData *imageData in [inputDictionary objectForKey:#"images"]) {
NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST"
URLString:url
parameters:parameters
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData
name:[NSString stringWithFormat:#"file%d",i]
fileName:[NSString stringWithFormat:#"abc%d.png",i]
mimeType:#"image/png"];
i++;
}
error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[mutableOperations addObject:operation];
}
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:mutableOperations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(#"%lu of %lu images uploaded!", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(#"All images have been uploade!");
}];
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
Actually I modified the same code and its working now. Changed the "Content-Type" to "multipart/form-data".
Also added the key (parameter name) for my imagesArray in the API request to the following method
"formData appendPartWithFileData:imageData name:#"yourKey"..."
if (_isUploadImage) {
__block int i=1;
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:url]];
[manager.requestSerializer setValue:#"multipart/form-data" forHTTPHeaderField:#"Content-Type"];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
if (_shouldBeInHeader) {
NSString *token = [SSKeychain passwordForService:RegistrationTokenKey account:LoggedInUserKey];
[manager.requestSerializer setValue:[NSString stringWithFormat:#"Token %#",token] forHTTPHeaderField:#"Authorization"];
}
NSDictionary *parameters = #{#"wave_id": [inputDictionary objectForKey:#"wave_id"]};
AFHTTPRequestOperation *op = [manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
for (NSData *imageData in [inputDictionary objectForKey:#"images"])
{
[formData appendPartWithFileData:imageData name:[NSString stringWithFormat:#"images"] fileName:[NSString stringWithFormat:#"abc%d.png",i] mimeType:#"image/png"];
i++;
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed");
}];
[op start];
}

Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: video/mp4"

I have video in server url then i'm downloading from url using AFNetworking for later playing the video. But while downloading i got below error
Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: video/mp4" UserInfo=0x1e8b6d30 {NSErrorFailingURLKey=http://center.net/projects/AR/Medica/focusvideo.mp4, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x1d55c260>, NSLocalizedDescription=Request failed: unacceptable content-type: video/mp4}
code for download the video:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"images"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"video/mpeg", nil];
[manager GET:#"http://center.net/projects/AR/Medica/focusvideo.mp4"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[operation.responseData writeToFile:[dataPath stringByAppendingPathComponent:#"focusvideo.mp4"] atomically:YES];
NSLog(#"Successfully downloaded file to %#", [NSURL fileURLWithPath:dataPath]);
NSLog(#"THE RESPONSE: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error1) {
NSLog(#"%#", error1);
}];
In AFURLResponseSerialization.m file Just add video/mpeg
in acceptable contact type.
Instead of :
self.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript",#"text/html", nil];
Use this :
self.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript",#"text/html",#"video/mpeg", nil];
If using AFNetworking 2.0, you can use the POST method, which simplifies this a bit:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"username":username, #"password":password};
[manager POST:#"https://mycompany.atlassian.net/rest/auth/latest/session/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
This does the creation of the request, setting its Content-Type according to the requestSerializer setting, and encodes the JSON for you. One of the advantages of AFNetworking is that you can get out of the weeds of constructing and configuring NSURLRequest objects manually.

How to download a file and save it to the documents directory with AFNetworking?

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

Resources