iOS NSURLConnection POST error handling - iphone

So for an iOS client of mine, I'm initiating a POST to upload a big chunk of data (say, 30MB), via:
[[NSURLConnection connectionWithRequest:req delegate:self] retain];
However, I need to handle the case where the URL is bad - say, one that returns a 404. The problem is, my didSendBodyData delegate method is called over and over, just like it should be assuming the URL is correct, in chunks of 32k worth of data, until it hits the 30MB total file size. I'm actually doing calculations in this method to show and display a progress bar, and even with an invalid URL, it looks and acts like it's transferring the whole file (I'm not sure what's really going on under the covers - it can't actually be doing anything, the URL resolves to a 404!)
THEN, after 20 seconds of supposed uploading, my didReceiveResponse delegate method is finally called, where I can check the NSURLResponse and see that a 404 was served up. Why does it seem like it transfers the entire file before I'm able to get any kind of error? Using [NSURLConnection connectionWithRequest], how can I know this was a 404 before it actually does anything? Is there anyway to tell in the didSendBodyData method, or any other way to tell earlier than what I'm seeing?
An even bigger problem is, I let you limit the upload time, so it stops after x number of seconds, at which point I cancel the connection (in the middle of the didSendBodyData method), so doing that there's seemingly no way to know anything even went wrong with the URL.
It seems like this should have a ridiculously easy solution, but I'm not seeing it. Thanks for any help.

Based on the spec, I don't believe that an HTTP server sends back an HTTP response until the HTTP request has been completely received. This means that even though you are sending a bunch of data to nowhere, the behavior you are seeing is expected.
You might try sending the HTTP Expect Header in your request. Otherwise, have you considered sending out a preliminary ping request to check if the url endpoint exists? Maybe a POST with no data? Then you can find out about the 404 before making the costly request.

Have you implemented the NSURLConnectionDataDelegate ?
As the following delegate methods could be what you're after:
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
if you just want to examine the response code and perform some action then I would add the following to your code
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 404){
NSLog(#"Epic Fail");
}
...
...
}

Related

How to check response for multiple requests in ASINetworkQueue?

I am using ASINetworkQueue to send multiple requests to the server one after another. I have 4 consecutive server calls.
I want to know whenever the response is received, I want to handle it in selector for queue. I have implemented handler method as well using
requestDidFinishSelector
I want to know how to get responsestring for each request individually? just like
[request responseString]
with normal http requests? How can I solve this? Thanks in advance.
Solved : solution found here in github itself
- (void)requestFinished:(ASIHTTPRequest *)request
{
//print or manipulate response here
}

Authentication for NSURLConnection when it is not required

I'm trying to download a file from google trends. I'm using NSURLConnection to get the file.
I want to let google know I'm logged in (ie authenticate the connection) in order to have no download limit. I tried using:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
The problem is since the login is not required, the method is never being called. Is there a way I can make sure the connection is authenticated? Thx!
Note: I asked this question before here, but I didn't get a reply so I'm asking again - hope that's ok
EDIT: Maybe I can use - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse ? Can I somehow authenticate through the cache?
you have to set the correct header fields of the NSURLRequest. Take a look at the answer of this post. You will have to look for base64 encoding too.

Identify file type from URL in an iPhone app

For an iPhone app, I am downloading files using URL:
From this type of url:: http://xxxxxxxxxxxxxxxxxxx.com/xxxxxxx//xxx/ipad.html?operation=getFile&contentId=61768b16-6b44-4d0b-bdcf-d10107d1f328
I am downloading files from server but it may be of type .pdf or .docx or .doc
Is there any way to identify file type from url?
No, since the filename is not in the URL you can not make an assumption.
But after you received the header for the URL they may tell you what kind of file you will receive.
In the follwing NSURLConnectionDelegate method
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSString *mimeType = [response MIMEType]
NString *suggestedFilename = [response suggestedFilename];
}
Of course it works only if you get them from server.
There's no indication of type in the URL you provided, and even if the URL did appear to specify a certain type of file (e.g. http://foo.com/bar.pdf) there's no guarantee that the server would actually return a PDF file.
If you don't want to download the file you can always make a HEAD request to get just the HTTP headers and look at the value of the Content-Type header. Or, you can put an Accept header in your request to restrict responses to a certain type of data.

How to identify whether response coming from server is pdf or url or image?

In my app, when I send request to server either I will get url or pdf or image in response and based on that I will display the result (url->webview, image->imageview etc).But I do not know how to identify whether the response is url or pdf or image?
Please anyone know how I can achieve this?
Thanks in advance!
I assume you do use NSURLConnection to download your file. So, implement this delegate method ...
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
... cast response to NSHTTPURLResponse and get Content-Type value from allHeaderFields.
But it depends what do you really use to download your files. If you do use another class/framework/..., you get an idea.
I would like to suggest you to use UIWebview for both case either it is PDF or image url from server.
[imgwebVw loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:strImgURL]]];
If you really must do this you can read the file headers but I wouldn't suggest it. here is a category I wrote to get the size of a remote image, you can adapt it to detect if the file is indeed an image or not. And you can do similar stream parsing to search for the PDF Header: %PDF-1.0 etc. Otherwise you would assume it is a url.

When does NSURLConnection's initWithRequest return nil

Does anyone know in which situations initializing a NSURLConnection returns nil instead of the created connection. The documentation says it's possible but fails to specify when this happens.
The method/message in question:
[[NSURLConnection alloc] initWithRequest:request delegate:self];
-
According to the NSURLConnection Class Reference:
Return Value: The URL connection for the URL request. Returns nil if a connection can't be initialized.
The URL Loading System Programming Guide says the following:
If NSURLConnection can’t create a connection for the request, initWithRequest:delegate: returns nil.
-
While it's possible that this method returns nil, I'm unable to come up with a scenario which triggers this. I've tried the following scenarios:
URLRequest with an empty url: connection:didFailWithError: delegate method is called with "unsupported URL" as error.
URLRequest with invalid url: connection:didFailWithError: delegate method is called with "bad URL" as error.
URLRequest with nonexistent url: connection:didFailWithError: delegate method is called with "A server with the specified hostname could not be found." as error.
Valid request but no internet: connection:didFailWithError: delegate method is called with "The Internet connection appears to be offline." as error.
nil request: causes a crash.
The initWithRequest method returned a valid NSURLConnection in each scenario (besides the last one) and called the connection:didFailWithError: with an appropriate error.
Has anybody been able to figure out which scenario does cause nil to be returned?
I believe this can also be used when it fails to load, not just initialize. (The alloc is done separately - that's where low mem would probably bite you) So (I'm guessing) it could fail because you did not have a network available (3G/Wifi) or it simply failed to connect to the server. In any event, use:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
To get the actual failure.
You may be able to simulate this with an absence of a network - or even giving it a bad URL.
I guess the answer is "Never". Seems only way for NSURLConnection to return nil is failing at [super init]. ([super init] returning nil) But as super class of NSURLConnection is NSObject and NSObjects init just returns self (never nil)
PS: That's for IOS SDK 4.0, on emulator, can be different on device.
I would try all of the above except do it during low memory conditions. IE, I think it will happen when an internal malloc fails.
I thing this is caused if the request u specified has wrong or not all essential values
NSURLConnection returns nil if it is not created inside a runLoop.