I am having a hard time sifting through search results for how to do this and I can't find anything concrete in the documentation. I just want to download a file and store in the Documents directory. The file is of type .plist, but I don't need to parse the plist. Like I said I just need to save it to disk.
Do I use AFHTTPRequestOperationManager for this?
This is what I've been trying in general:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//manager.responseSerializer = [AFPropertyListResponseSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:url parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DLog(#"downloaded plist");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(#"JSON DataError: %#", error);
}];
If I use AFHTTPResponseSerializer I get this:
Error Domain=AFNetworkingErrorDomain Code=-1011 "Request failed: internal server error (500)"
If I use AFPropertyListResponseSerializer I get this:
Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: text/plain"
But I'm not even sure I'm using the correct API.
Please, try this example.
Hope this help!
// Step 1: create NSURL with full path to downloading file
// for example try this: NSString *fileUrl = #"https://pbs.twimg.com/profile_images/2331579964/jrqzn4q29vwy4mors75s_400x400.png";
// And create NSURLRequest object with our URL
NSURL *URL = [NSURL URLWithString:fileUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
// Step 2: save downloading file's name
// For example our fileName string is equal to 'jrqzn4q29vwy4mors75s_400x400.png'
NSString *fileName = [URL lastPathComponent];
// Step 3: create AFHTTPRequestOperation object with our request
AFHTTPRequestOperation *downloadRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request];
// Step 4: set handling for answer from server and errors with request
[downloadRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// here we must create NSData object with received data...
NSData *data = [[NSData alloc] initWithData:responseObject];
// ... and save this object as file
// Here 'pathToFile' must be path to directory 'Documents' on your device + filename, of course
[data writeToFile:pathToFile atomically:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"file downloading error : %#", [error localizedDescription]);
}];
// Step 5: begin asynchronous download
[downloadRequest start];
Something else: What's the best way to find the user's Documents directory on an iPhone?
Related
I am very new to iOS. I am trying to send data through post method to PHP. In PHP it can't take data like $_POST['data'], but it takes $_GET['data']. My iOS code is as follows.
NSString *strURL = [NSString stringWithFormat:#"http://example.com/app_respond_to_job?emp_id=%#&job_code=%#&status=Worker-Accepted&comment=%#",SaveID2,txtJobcode1,alertTextField.text];
NSURL *apiURL = [NSURL URLWithString:strURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:apiURL];
[urlRequest setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
_receivedData = [[NSMutableData alloc] init];
[connection start];
NSLog(#"URL---%#",strURL);
Can someone explain why is that, it will be very helpful.
Please Download this file https://www.dropbox.com/s/tggf5rru7l3n53m/AFNetworking.zip?dl=0
And import file in your project
Define in #import "AFHTTPRequestOperationManager.h"
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"Your Url"]];
NSDictionary *parameters = #{#"emp_id":SaveID2,#"job_code":txtJobcode1.text,#"status":alertTextField.text};
AFHTTPRequestOperation *op = [manager POST:#"rest.of.url" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[responseObject valueForKey: #"data"];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[op start];
because you send your data via query string in url
i think it will work if you try to pass data in your request's body:[urlRequest setHTTPBody:...]
POST parameters come from the request body, not from the URL string. You'll need to:
Call setHTTPBody on the request and provide the URL-encoded string (sans question mark, IIRC) as the body data
Call setValue:forHTTPHeaderField: to set the Content-Type to application/x-www-form-urlencoded
Either remove the call to [connection start] or use initWithRequest:delegate:startImmediately: so that you aren't starting the connection twice.
That last one is kind of important. You can get strange results if you try to start a connection twice. :-)
unable to download file
getting this error "Client closed connection before receiving entire response"
the file which i am trying to download is just 266KB
for (NSString *downloadURL in arr) {
// NSString *downloadURL = [d objectForKey:#"url"];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"URL for downloading : %#",downloadURL);
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *downloadedZipPath = [documentsDirectory stringByAppendingPathComponent:TEMP_DICTIONARY];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:downloadURL]];
// [request addValue:#"bytes=x-" forHTTPHeaderField:#"Range"];
// [request setTimeoutInterval:20];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:downloadedZipPath append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation start];
});
tried to increase api request time out but still not working
Try setting it to more time
[request setTimeoutInterval:20];
I have some error like this. But I think it is not the AF faults. When the thing's content-type you request is different from it's original content type this error will come out.
For Example:
When you request a mp4 file, the server should set the content-type to video/mpeg4, or you can change your request type from GET to POST.
I want to access Twilio api using AFNetworking. I tried number of ways but not get success. Please help me, if anyone did Tiwilo post request using AFNetworking.
Case 1: This is my native objective-c working code.
NSString *urlString = [NSString stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages", kTwilioSID, kTwilioSecret, kTwilioSID];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSString *bodyString = [NSString stringWithFormat:#"From=%#&To=%#&Body=%#", from, to, message];
NSData *data = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError)
{
DLog(#"Error: %#", connectionError);
completionBlock(connectionError, NO);
}
else
{
completionBlock(connectionError, YES);
}
}];
Case 2: Using AFNetorking: Code that is not working:
Code:
NSString *urlString = [NSString stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages", kTwilioSID, kTwilioSecret, kTwilioSID];
NSDictionary *dict = #{
#"From" : from,
#"To" : to,
#"Body" : message
};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:urlString parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Success: %#", responseObject);
}
failure:
^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Related Error:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x1775e660 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set., NSUnderlyingError=0x175101b0 "Request failed: bad request (400)"}
Case 3: Using AFNetorking: Another Code that is also not working:
Code:
NSString *urlString = [NSString stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages", kTwilioSID, kTwilioSecret, kTwilioSID];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSString *bodyString = [NSString stringWithFormat:#"From=%#&To=%#&Body=%#", from, to, message];
NSData *data = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error);
}];
[operation start];
Related Error:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x177a3e70 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
Thank you.
Ricky from Twilio here. First off a quick disclaimer. Making a request to Twilio directly from an iOS app requires you to embed your Twilio account credentials in the app, which is dangerous. My recommendation would be to send the SMS from a server side script that your app makes a request to in order to keep your credentials safe.
That being said, your code is really close. By default, Twilio's REST API returns XML. If you want to parse the response as it's returned by default you can update the code in version 2 to use the AFXMLParserResponseSerializer:
operation.responseSerializer = [AFXMLParserResponseSerializer serializer];
If you'd rather work with JSON then you update the Twilio URL you're making the POST request to and indicate you'd like a JSON response:
NSString *urlString = [NSString stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages.json", kTwilioSID, kTwilioSecret, kTwilioSID];
Hope that helps.
I'm doing a simple request in order to download PDF files and then write it to the file path.
Some of the PDF's are getting directed to the fail block.
The error code I'm getting is 200 and the error description is "transfer closed with 2231939 bytes remaining to read".
Below is the code snippet.
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:nil
timeoutInterval:120];
AFHTTPRequestOperation *downloadRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[downloadRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if (operation.response.statusCode != 200) {
NSLog(#"Error code(S): %d",[operation.response statusCode]);
}else{
NSData *data = [[NSData alloc] initWithData:responseObject];
[data writeToFile:filePath atomically:YES];
NSLog(#"successful download to %#", filePath);
[data release];
}
[self fetchComplete:operation type:type];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error code: %d",[operation.response statusCode]);
NSLog(#"error discreption: %#",[error localizedDescription]);
[self fetchFailed:operation];
}];
Please, try this example. Hope this help!
// Step 1: create NSURL with full path to downloading file
// for example try this: NSString *fileUrl = #"https://pbs.twimg.com/profile_images/2331579964/jrqzn4q29vwy4mors75s_400x400.png";
// And create NSURLRequest object with our URL
NSURL *URL = [NSURL URLWithString:fileUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
// Step 2: save downloading file's name
// For example our fileName string is equal to 'jrqzn4q29vwy4mors75s_400x400.png'
NSString *fileName = [URL lastPathComponent];
// Step 3: create AFHTTPRequestOperation object with our request
AFHTTPRequestOperation *downloadRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request];
// Step 4: set handling for answer from server and errors with request
[downloadRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// here we must create NSData object with received data...
NSData *data = [[NSData alloc] initWithData:responseObject];
// ... and save this object as file
// Here 'pathToFile' must be path to directory 'Documents' on your device + filename, of course
[data writeToFile:pathToFile atomically:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"file downloading error : %#", [error localizedDescription]);
}];
// Step 5: begin asynchronous download
[downloadRequest start];
I'm using the following code to set up my operation manager:
requestSerializerJson = [AFJSONRequestSerializer serializer];
[requestSerializerJson setValue:[taskHandler getBranchesApiConstantForName:#"header_value_content_type"] forHTTPHeaderField:[taskHandler getBranchesApiConstantForName:#"header_name_content_type"]];
[requestSerializerJson setValue:[taskHandler getBranchesApiConstantForName:#"header_value_api_key"] forHTTPHeaderField:[taskHandler getBranchesApiConstantForName:#"header_name_api_key"]];
httpRequestOperationManager = [AFHTTPRequestOperationManager manager];
httpRequestOperationManager.requestSerializer = requestSerializerJson;
httpRequestOperationManager.responseSerializer = [AFJSONResponseSerializer serializer];
httpRequestOperationManager.operationQueue = [[NSOperationQueue alloc] init];
httpRequestOperationManager.operationQueue.maxConcurrentOperationCount = 1;
Then, I've got a method to download multiple JSON strings:
- (void)downloadBranches {
NSLog(#"Test %#", httpRequestOperationManager.requestSerializer.HTTPMethodsEncodingParametersInURI);
for (NSString *branchUuid in taskHandler.addedBranchesUuids) {
NSString *urlString = [NSString stringWithFormat:#"%#%#%#", urlBase, [taskHandler getBranchesApiConstantForName:#"getbranch_suffix"], branchUuid];
NSURL *URL = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSLog(#"Test %#", request.allHTTPHeaderFields);
AFHTTPRequestOperation *op = [httpRequestOperationManager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[httpRequestOperationManager.operationQueue addOperation:op];
}
}
All the operations are performed but I get a message from the server which says that I didn't supply the authentication key.
I specifically set it in the 3rd line - for the requestSerializerJson which is then added to the httpRequestOperationManager so all of the requests should be using the headers.
I added an NSLog to print request.allHTTPHeaderFields but it says "(null)".
How can I fix this?
downloadBranches is completely bypassing the serializer by building an NSURLRequest manually. The whole point of the serializer is to do that for you.
You need to call requestWithMethod:URLString:parameters: on your serializer, which will return an NSURLRequest with the headers you want.
Or just use the operation manager's GET:… method inside that for loop; your use case doesn't look like it requires this other stuff at all.