In my iOS app I need to load an image from web, but this image is on a server in which it's necessary to give username and password. I tried to use this code:
- (void) loadImageFromWeb:(NSString *)urlImg {
NSURL* url = [NSURL URLWithString:urlImg];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
[self.imageObjectScanned setImage:image];
} else {
NSLog(#"ERRORE: %#", error);
}
}];
}
But it return an error and says that:
Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x14e6b420 {NSErrorFailingURLKey=http://54.204.6.246/magento8/media/catalog/product/cache/0/image/9df78eab33525d08d6e5fb8d27136e95/s/c/scheda_non_shop.jpg, NSErrorFailingURLStringKey=http://54.204.6.246/magento8/media/catalog/product/cache/0/image/9df78eab33525d08d6e5fb8d27136e95/s/c/scheda_non_shop.jpg, NSUnderlyingError=0x14e695c0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)"}
I guess this error it's because I'm not sending the username and the password. How I can send username and password to load this image?
Try adding the basic authentication in header of your request object.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSString *authCredentials = [NSString stringWithFormat:#"%#:%#", userName, password];
NSString *authValue = [NSString stringWithFormat:#"Basic %#",[authCredentials base64EncodedStringWithWrapWidth:0]];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
[self.imageObjectScanned setImage:image];
} else {
NSLog(#"ERRORE: %#", error);
}
}];
Download the Base64.h/.m files from here and import it into your project.
Add header #import "Base64.h" in your implementation file.
This GitHub-issue suggests that your server is using an incorrect SSL certificate:
https://github.com/RestKit/RestKit/issues/1511
But if it is a credentials-issue, I suggest looking at NSURLCredential
https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Classes/NSURLCredential_Class/Reference/Reference.html
You can present the credentials in a delegate method to NSURLConnection, or store them once and let them be used for all requests.
Alternatively, you could take a look into using RestKit.
You may try to pass the credentials within the URL as a query component, as described in the official documentation:
If authentication is required in order to download the request, the required credentials must be specified as part of the URL. If authentication fails, or credentials are missing, the connection will attempt to continue without credentials.
The parameters which comprises the query component need to be properly encoded. You may use this method to encode the parameters for a URL shown in this answer.
For example:
NSDictionary* parameters = #{#"login": name, #"password": password};
NSData* queryComponent = [parameters dataFormURLEncoded];
NSString* queryComponentString = [NSString alloc] initWithData:queryComponent
encoding:NSUTF8StringEncoding];
NSString* urlString = [NSString stringWithFormat:#"%#?%#",
urlImg, queryComponentString];
NSURL* url = [NSURL URLWithString: urlString];
A small caveat:
The described method which encodes the parameter included in the query component for a URL follows strictly the suggested algorithm specified by w3c: The application/x-www-form-urlencoded encoding algorithm which should be applied for URLs.
This encoding algorithm will escape a tilde character ~ when it occurs in either the name or value string. However, according the more general rules to compose a URL (see RFC 3986), the tilde character should not be escaped. I don't think this will ever be a problem, though.
Related
I got the following response while getting my Photo from Instagram. Please help any help would be appreciated.
{
code = 403;
"error_message" = "Invalid signed-request: Missing required parameter 'sig'";
"error_type" = OAuthForbiddenException;
}
Here is my code
NSURL *url = [NSURL URLWithString:#"https://api.instagram.com/v1/tags/nofilter/media/recent?access_token=...........aef2"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error){
}
else {
NSString * a = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *tokenData = [jResponse objectWithString:a];
NSLog(#"%#",tokenData);
}
}];
Looks like you have enabled Enforce Signed Requests, so it requires you to have sig parameter which is signature for API request, described here: https://www.instagram.com/developer/secure-api-requests/
Either generate the signature or disable Enforce Signed Requests
Looks like you are making API call from an app (client side), so it is not recommended to make signed request, since u have to save the client_secret in the app code. It is recommended to do this on the server to be secure. So just disable the Enforce Signed Requests for you app and make API call as is.
A continution for #krisrak answer.
To disable Enforce Signed Requests.
Goto https://www.instagram.com/developer/clients/manage/
Select your Client required. Go to Security.Uncheck the Enforce signed requests
And save the updated changes.
I want calling method webService by parameter Json from IOS, but I received an error.
Code Server Side (WCF):
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/test/{input}")]
int test(string input);
I want get input (parameter method and url) = typeof (Json)
Code Client Side (iOS-objective C) :
NSString *json = [self convertToJson:myObject];
NSString *urlComplete = [NSString stringWithFormat:#"%#%#",#"http://test.com/Service.svc/test/",json];
urlComplete = [urlComplete stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:[NSURL URLWithString:urlComplete]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:
^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data.length > 0 && connectionError == nil) {
NSString *string = [[NSString alloc]initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"Data Recived:\n %#",string);
}
else{
NSLog(#"Error %#",[connectionError description]);
}
}];
The webService is being tested by windowsPhone and returns OK but doesn't work with iOS.
Please help me!
thanks:)
Error description "HTTP Error 400. The request URL is invalid." clears that url you are passing is incorrect. Please cross check with windows team if they are appending the JSON to the get URL.
Generally, if you want to post data you can set the requestdata which is JSON and go for either a PUT or POST request instead of GET request.
I'm practicing how to parse XML data and store it into the sqlite. I have done parsing and storing successfully. But I have one problem with displaying image from an url. The URL is formed by combining two NSStrings. One for the fixed address(which I set value) and other based on the name of the photo(retrieved from Sqlite). I am able to create complete URL by retrieving name of photo from Sqlite. But strange thing happen when I use that URL to display image in UIImageView. It does not work. After some testing, I found out there is something wrong with the portion(photo name) I retrieved from Sqlite. If I combine the fixed address with literal name of the photo, it works. Can somebody explain why it happens like this. Thanks in advance.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"user.db"];
FMDatabase * database = [FMDatabase databaseWithPath:defaultDBPath];
[database open];
results=[database executeQuery:#"SELECT * FROM plant WHERE name=?",self.plantname];
while([results next]) {
name = [results stringForColumn:#"name"];
category = [results stringForColumn:#"category"];
instructions = [results stringForColumn:#"instructions"];
price = [results stringForColumn:#"price"];
photo=[results stringForColumn:#"photo"];
}
NSString * fixedURL = #"http://services.hanselandpetal.com/photos/";
NSString *url=[fixedURL stringByAppendingString:photo];
NSLog(url);
NSURL * imgURL = [NSURL URLWithString:url];
NSData * imageData = [NSData dataWithContentsOfURL:imgURL];
UIImage * image = [UIImage imageWithData:imageData];
self.plantImageView.image=image;
Edit
I've edited based on Rob answer. But there are still problems. I put log below. I've already tried to remove white spaces by using [photo stringByReplacingOccurrencesOfString:#" " withString:#""]. But it does not seem to affect.
2014-10-15 02:12:39.505 SqlitePractice[9256:286525] url string = 'http:/services.hanselandpetal.com/photos/mona_lavender.jpg'
2014-10-15 02:12:39.506 SqlitePractice[9256:286525] imgURL = (null)
2014-10-15 02:12:39.516 SqlitePractice[9256:286525] sendAsynchronousRequest failed: Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo=0x7a78ba50 {NSUnderlyingError=0x7a66b5e0 "unsupported URL", NSLocalizedDescription=unsupported URL}
Edit 2
The URL seems to be problem after changing from stringByAppendingString to stringByAppendingPathComponent. But I found out that even without one slash after http: , it works if I change the photo value. And the image is displayed.
NSString * fixedURL = #"http://services.hanselandpetal.com/photos/";
photo=#"bougainvillea.jpg";
NSString *url=[fixedURL stringByAppendingPathComponent:photo];
NSLog(#"url string = '%#'", url);
NSURL * imgURL = [NSURL URLWithString:url];
NSLog(#"imgURL = %#", imgURL);
And the log is below,
2014-10-15 12:07:56.650 SqlitePractice[9690:308022] url string = 'http:/services.hanselandpetal.com/photos/bougainvillea.jpg'
2014-10-15 12:07:56.651 SqlitePractice[9690:308022] imgURL = http:/services.hanselandpetal.com/photos/bougainvillea.jpg
Edit 3
I have changed based on Rob's modified answer.
NSURL *fixedURL = [NSURL URLWithString:#"http://services.hanselandpetal.com/photos/"];
NSURL *url = [fixedURL URLByAppendingPathComponent:[photo stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"image URL = '%#'", url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"sendAsynchronousRequest failed: %#", error);
return;
}
UIImage *image = [UIImage imageWithData:data];
self.plantImageView.image=image;
}];
And here is the log message:
2014-10-15 13:40:38.977 SqlitePractice[10436:357359] image URL = 'http://services.hanselandpetal.com/photos/camellia.jpg%250A%2520%2520%2520%2520'
A couple of thoughts:
Unrelated to your problem at hand, instead of stringByAppendingString, it's generally better to use URLByAppendingPathComponent with a NSURL. It takes care of adding any necessary / characters for you. Not critical given your example, but it's more robust.
Also, if the string might have spaces or other characters not permitted in a URL, you might percent escape it, too.
Thus, you'd do something like:
NSURL *fixedURL = [NSURL URLWithString:#"http://services.hanselandpetal.com/photos/"];
NSURL *url = [fixedURL URLByAppendingPathComponent:[photo stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
You should NSLog the NSURL variable and make sure it's not nil (e.g. which could be caused if there were some spaces in the photo string, for example, unless you percent escape it).
In your revised question, in which you share the log, the original URL string (before the conversion to the NSURL) is being reported as:
http:/services.hanselandpetal.com/photos/mona_lavender.jpg
That should be:
http://services.hanselandpetal.com/photos/mona_lavender.jpg
If imgURL is not nil, but imageData is, you might want to retrieve the image data in a manner that retrieves the error. For example, you could:
NSError *error = nil;
NSData *imageData = [NSData dataWithContentsOfURL:imgURL options:0 error:&error];
if (!imageData) {
NSLog(#"dataWithContentsOfURL failed: %#", error);
}
Bottom line, go through this one line at a time and identify precisely where it is going wrong.
As an aside, you generally would want to avoid using dataWithContentsOfURL, but instead use an asynchronous method:
NSURL *fixedURL = [NSURL URLWithString:#"http://services.hanselandpetal.com/photos/"];
NSURL *url = [fixedURL URLByAppendingPathComponent:[photo stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NRURLRequest *request = [NSURLRequest requestWithURL:imgURL];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"sendAsynchronousRequest failed: %#", error);
return;
}
UIImage *image = [UIImage imageWithData:data];
self.plantImageView.image=image;
}];
I belive that UIIMAGEVIEW will not display Url as image path. I would sugest to try with UIWebView which would display web content (image or whole web page). This example is writen in objective-c.
self.myWebView = [[UIWebView alloc] initWithFrame:self.view.bounds];
self.myWebView.scalesPageToFit = YES ;
[self.view addSubview:self.myWebView];
NSURL *url = [NSURL URLWithString:#"http://services.hanselandpetal.com/photos/mona_lavender.jpg"];
NSURLRequest *request = [ NSURLRequest requestWithURL:url];
[self.myWebView loadRequest:request]
The url below downloads a file without an extention including busstations and times. The data is fetched in an iPhone-app that displays bustimes called mobitime. The problem is that I can't find out what encoding the data is. Is there any way to find out?
Thanks!
http://d2.mobitime.se/cgi/mtc/sad?uuid=01b07052fa390ceb845405e3d0547f7e&r=4&id=191430&no=721&to=Odensbacken%20via%20Ekeby-Almby&lang=sv
There are two techniques that I know of:
You can look at the HTTP headers and see if it reports anything useful:
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (id)response;
NSLog(#"httpResponse.allHeaderFields = %#", httpResponse.allHeaderFields);
}
}];
Those headers report "Content-Type" = "text/plain"; which obviously is not the case.
Sometimes you can also use the usedEncoding option of one of the initWithContentsOfURL method:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSStringEncoding encoding;
NSError *error;
NSString *string = [[NSString alloc] initWithContentsOfURL:url usedEncoding:&encoding error:&error];
if (error)
NSLog(#"%s: initWithContentsOfURL error: %#", __FUNCTION__, error);
if (string)
NSLog(#"encoding = %d", encoding);
});
But that reports an error (suggesting, again, that this might not be a string encoding at all).
In short, I'd suggest you contact the provider of that web service, and ask them regarding the format. But looking at the hex dump, I don't recognize the format. With a passing glance at it, it looks like binary data, not any string encoding.
Is it possible to use the sendAsynchronousRequest of NSURLConnection knowing the requested url will have a redirect and all request must also use basic auth?
I am getting the following error: Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)
I did write some code using the NSURLConnectionDelegate and modified the redirect request to add the basic auth in the header and that worked.
So I'm guessing it has something to do with the authentication not being set on the second request. The same with the Delegate, If I didn't set the basic auth on the redirect request things were failing with a HTTP 401 unauthorized
It is possible I believe as I am doing it currently, here's my code, the trick is to set the header for "Authorization" with "Basic base64encodedmethod(username:password)"
//SETUP URL
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://YOURURLHERE"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:90.0];
//Get the username & password - then encode the values with Base64 (i googled for a library)
NSString *userAndPassword = [NSString stringWithFormat:#"%#:%#",userName,password];
NSString *encodedString = [userAndPassword base64EncodedString];
//Set the Authorization header which will now let your service calls pass basic authentication
[request addValue:[NSString stringWithFormat:#"Basic %#",encodedString] forHTTPHeaderField:#"Authorization"];
//Setup a queue and call the async request - remember to do items in your block on the
//main thread if it's for things like showing/hiding items as other threads will not run that code when you're expecting it
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//your code block here
}];
I believe that answers your question, now I just need to find out how to delete that authentication so I can log the user out as I'm building this for a secure legal site. Any help there would be appreciated