AFHTTPRequestOperation nil response instead of error - ios

I am using AFHTTPRequestOperation to get a couple of HTML pages to parse.
The problem i'm having, is if I use a wrong port number for example, when connecting to the server, the 'failed' error block doesn't fire. Instead the completion block fires but the responce string is nil.
I'm just switching over to AFNetworking from ASIHTTP, and with ASIHTTP this would produce an error.
Surely this should provide an error? How can I trap this?
NSString *urlString;
urlString = [NSString stringWithFormat:#"%#://%#:%#/",kHttp,_IP,_Port];
NSURL *url = [NSURL URLWithString:urlString];
// Set authorization
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setAuthorizationHeaderWithUsername:_User password:_Pass];
NSURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"Info.htm" parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([self parseInfoLive:operation.responseString])
_count_parsed++;
if (_count_parsed == 2)
[[NSNotificationCenter defaultCenter] postNotificationName:#"downloadsComplete" object:nil];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error during connection: %#",error.description);
[[NSNotificationCenter defaultCenter] postNotificationName:#"errorConnecting" object:nil];
}];
[operation start];

This seems to be a bug in AFNetworking, even 2.5 years after this question. This occurs when response contains a special character(it can appear as a space since sometimes even text viewers too can't parse it). You can try converting recieved JSON string to NSUTF8StringEncoding and then use it as NSData, if needed.
NSURL *url = <YOUR REQUEST URL>
NSString *data = [NSString stringWithContentsOfURL:url];
NSData *metOfficeData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = [NSError new];
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:metOfficeData options:kNilOptions error:&error];

Related

Client closed connection before receiving entire response AFNetworking

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.

How to use AFNetworking to create JSON array

I am currently trying to create a JSON array like I do here like this:
NSURL *url = [NSURL URLWithString:currentJSON];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
if (jsonData) {
result = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&error];
}
Which works fine. Apart from I want it to time out if the internet connection is not great.
So I then wen to AFNetworking where I wrote code like this:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:currentJSON parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSError *error = nil;
result = [NSJSONSerialization JSONObjectWithData:responseObject
options:NSJSONReadingMutableContainers
error:&error];
[[NSUserDefaults standardUserDefaults] setObject:result forKey:#"All"];
[[NSUserDefaults standardUserDefaults] synchronize];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
result = [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"All"];
}
But this method always runs to a failure How come? What am I doing wrong?
Check that server is sending JSON using correct content type 'application/json'. AFNetowrking checks this out of the box and if receives something else (for example 'text/html'), failure block will be called.
Also AFNetworking does JSON to object parsing out of the box. 'id responseObject' is already the result of '[NSJSONSerialization JSONObjectWithData]'.
If you can't change content type sent by server, you could add that content type to accepted types using following snippet
NSMutableSet *accepted = [NSMutableSet set];
[accepted addObject:#"text/html"];
[accepted addObject:#"application/json"];
manager.responseSerializer.acceptableContentTypes = accepted;
Try this :
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
result = (NSDictionary *)responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[operation start];

Stop currently running HTTP Post operation on popViewController

The following code is used to make a post request to a server using AFHTTPClient:
NSURL *url = [NSURL URLWithString:urlString];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
//objects and keys
nil];
[httpClient postPath:postPath parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
id results = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONWritingPrettyPrinted error:nil];
//completion block
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#",error);
}];
[httpClient release];
But I noticed the request is still running even when the user has popped from the current viewController (noticed when a timed out error was logged, when on another viewController).
How do stop the request, when the viewController is no longer in the view hierarchy.
You can do this:
[[httpClient operationQueue] cancelAllOperations];
or this :
[self cancelAllHTTPOperationsWithMethod:#"POST" path:#"/path"];
You can put one of them in your viewWillDisappear;

AFNetworking Get full http response

I am querying my server using AFNetworking, the latest - to date - version.
My server side PHP is sending a PHP related error but I am unable to see what the error is ( so I can debug it) as AFNetworking is expecting a JSON.
Could anyone tell me how could I see the full HTTP result. I've researched and I know is something to do with operation.responseString inside the success / fail block my current block does not have AFHTTPRequestOperation* operation and I can't add it as another block variable somehow.
I would really appreciate some help.
The following code uses
NSURL *url = [[NSURL alloc]initWithString:URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:url];
NSURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:URLPATH parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
//...
}
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
NSLog(#"Inside the success block %#",JSON);
[[self delegate ]shareExerciseDone:JSON];
[[self delegate] activityIndicatorFinish];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(#"Response text is: %#", operation.responseString);
NSLog(#"json text is: %#", JSON);
NSLog(#"Request failed with error: %#, %#", error, error.userInfo);
[[self delegate] activityIndicatorFinish];
}];
[operation start];
The error
Request failed with 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=0xc1b4520 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}, {
NSDebugDescription = "JSON text did not start with array or object and option to allow fragments not set.";
Don't use AFJSONRequestOperation, just use AFHTTPRequestOperation.
For Uploading Images From iOS to Server i am using Afnetworking
can you try with this Code.and you will get response in success or failure.
NSData *userImgToUpload = UIImagePNGRepresentation(userImg.image);
NSURL *url = [NSURL URLWithString:#"www.domainname.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSLog(#"%#",#"Uploading data");
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:usernameTxt.text,#"username", firstnameTxt.text,#"first_name",lastnameTxt.text,#"last_name", nil];
// Upload Image
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/addPatient" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:userImgToUpload name:#"patientimage" fileName:[NSString stringWithFormat:#"%#.png",usernameTxt.text] mimeType:#"image/png"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"response: %#",[operation.responseString objectFromJSONString]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Upload Failed");
NSLog(#"error: %#", [operation error]);
}];
[operation start];
You should listen for the AFNetworkingOperationDidStartNotification and AFNetworkingOperationDidFinishNotification events that fire at the beginning and end of the operation:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(YourOperationStartMethod:)
name:AFNetworkingOperationDidStartNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(YourOperationFinishMethod:)
name:AFNetworkingOperationDidFinishNotification
object:nil];
You can grab the operation object from the notification like this:
AFHTTPRequestOperation *operation =
(AFHTTPRequestOperation *) [notification object];
This operation object contains request and response properties.
A good example of how all this works can be found in the AFHTTPRequestOperationLogger plugin (which, of course, you could simply use, instead of writing your own thing).

AFNetworking - Upload video along with other parameters

I want to upload video to web service along with some other parameters. I want to upload userID, videoID and video to web service. While uploading, all the parameters other than video is being sent to web service. I've checked at web service end, and the video is not coming with the request. I am using the following code.
- (void)uploadVideoAtLocalPath:(NSString *)videoPath videoID:(NSString *)videoID userID:(NSString *)userID {
NSString *strServerURL = #"www.mysite.com/user/uploadVideo";
NSURL *URL = [NSURL URLWithString:strServerURL];
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:URL];
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
// userID
NSData *userIDData = [userID dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData:userIDData name:#"userID"];
// videoID
NSData *videoIDData = [videoID dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData:videoIDData name:#"videoID"];
// video
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
[formData appendPartWithFileData:videoData name:#"video" fileName:#"video.mov" mimeType:#"video/quicktime"];
}];
[request setURL:URL];
[request setTimeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[AFHTTPRequestOperation addAcceptableStatusCodes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(100, 500)]];
[operation setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response String: %#", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
[client enqueueHTTPRequestOperation:operation];
}
Could anyone let me know whether I am doing it correct? If not, could anyone please tell me how to upload video to web service along with other parameters?
Thanks Everyone!
I'm not well in this method. I had the same issue. But, i have fixed it like mixing of POST & GET methods. I just sent my parameters as GET method like below -
NSString *strServerURL = [NSString stringWithFormat:#"www.mysite.com/user/uploadVideo&userID=%d&videoID=%d", 1, 55];
and, sent my video data in POST method as per your method -
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
// video
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
[formData appendPartWithFileData:videoData name:#"video" fileName:#"video.mov" mimeType:#"video/quicktime"];
}];
You better try to modify your webservice and try like above way. It should works.
Cheers!

Resources