Change Download File Name in Cocoahttpserver - iphone

I'm using cocoahttpserver in an iphone app, but when I try to download it (by clicking a link in the standard demo app), my sqlite file (myDatabase.sqlite) arrives on my Mac Desktop as "Unknown" with no suffix at all. However, when I "Save As..." it provides the name fine. I would prefer it to save the file with the sqlite suffix.
So, it must be the suffix causing the problems????
If this is the problem, I cannot seem to find a way in the classes to download the correct file name BUT then change it when presenting it to the browser (with a suffix like .backup, or .db, or something that works).
Anyone know where in the classes to change the download file name so the browser (Safari) will not call it "unknown"? Thanks.

The proper way to do this is to use the httpHeaders override in your async file class:
- (NSDictionary *)httpHeaders
{
NSString *key = #"Content-Disposition";
NSString *value = [NSString stringWithFormat:#"attachment; filename=\"%#\"", [filePath lastPathComponent]];
return [NSDictionary dictionaryWithObjectsAndKeys:value, key, nil];
}

I found someone else's code (MyAppSales) and in replyToHTTPRequest, I added the Content-Disposition header as below (in one section of the method), and now it works!
if(!isRangeRequest)
{
// Status Code 200 - OK
response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
NSString *contentLengthStr = [NSString stringWithFormat:#"%qu", contentLength];
CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), (CFStringRef)contentLengthStr);
// ************* added this from MyAppSales
if ([httpResponse isKindOfClass:[HTTPFileResponse class]])
{
NSString *baseName = [(NSString *)[(HTTPFileResponse *)httpResponse filePath] lastPathComponent];
NSString *contentDispoStr = [NSString stringWithFormat:#"Content-Disposition: attachment; filename=\"%#\"", baseName];
CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Disposition"), (CFStringRef)contentDispoStr);
}
}

I had a same problem and solved it by changing client side code. At the client side I add download attribute to tags.
Download
For Example:
Download

Related

How to parse HTML page data in iphone app?

I don't know how to parse HTML page content in iPhone SDK?
I have an iPhone app, in this app I need to show the image and data from the HTML page. I have an HTML page URL, I need to get data from the HTML page URL. Can anyone please guide me to parse HTML content from HTML page and show in iPhone app?
Can you please help me?
EDIT
I have an website in HTML format like this http://www.example.com/mobile/403.html page. I want to develop a native iPhone app for this website. My client wont give the response in XML feed so i need to use this site and parse the HTML contents. This page having many images, live data and tables. Till now i didn't parsed HTML page/content in iPhone SDK. So i need your help to do this? Can you please help me? I hope it is clear comparing with old question. Thanks in advance.
You can add the the image url to the NSMutableArray as code below..
NSMutableArray *array = [[NSMutableArray alloc] init];
NSString *response = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"index1" ofType:#"html"] encoding:NSUTF8StringEncoding error:nil];
// NSLog(#"response == %#", response);
NSString *regexStr = #"<a href=\"([^>]*)\">";
//NSString *regexStr = #"<A HREF=\"([^>]*)\">";
NSError *error;
NSInteger i =0;
// NSInteger length =0;
while (i<[response length]) {
NSRegularExpression *testRegex = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:&error];
if( testRegex == nil ) NSLog( #"Error making regex: %#", error );
NSTextCheckingResult *result = [testRegex firstMatchInString:response options:0 range:NSMakeRange(i, [response length]-i)];
// NSLog(#"result == %#",result);
NSRange range = [result rangeAtIndex:1];
if (range.location == 0) {
break;
}
NSString * imageUrl = [response substringWithRange:range];
if ([imageUrl hasSuffix:#".jpg"] || [imageUrl hasSuffix:#".gif"] || [imageUrl hasSuffix:#".tiff"] || [imageUrl hasSuffix:#".JPG"] || [imageUrl hasSuffix:#".JPEG"] || [imageUrl hasSuffix:#".png"] || [imageUrl hasSuffix:#".PNG"] || [imageUrl hasSuffix:#".GIF"] || [imageUrl hasSuffix:#".TIFF"]) {
// NSLog(#"%#",imageUrl);
// imageUrl = [imageUrl stringByReplacingOccurrencesOfString:#"/syneye_Portfolio/" withString:#""];
[array addObject:imageUrl];
//[array retain];
}
i= range.location;
//NSLog(#"%i",range.location);
i=i+range.length;
}
You should get the HTML thanks to a networking framework (AFNetworking for instance) and parse it with one of the following options:
custom code
some HTML parsing framework (i don't know any)
loading the HTML in a hidden UIWebView and doing some Javascript inside with stringByEvaluatingJavaScriptFromString:
I still don't understand exactly what you want, but this is what's possible with urls and html pages:
1) The page can be loaded into Safari. Of course a user can do this if the user has the url. But also a native app can launch Safari and supply Safari with the url of the page to load. A native app cannot however launch Safari and give it the actual html page to load, it must the url.
2) A native app can use UIWebView to either a) download and display a html page given a url or: b) If the html exists on the device, then the html page is given to UIWebView then the UIWebView will display it directly.
3) If the intention is to just extract a bit of text or an image or two from the html and then display it,then search for a few postings/tutorials then you can a) load the html page in a hidden UIWebView and use Javascript to access the dom elements or b) if its xhmlt use an xml parser to extract the html tags you are looking for or c) see if there are html parsing frameworks available for html or d) do a hack and string seach for the html tokens in the html directly.
4) Parse the full HTML and display all its contents yourself. Unless this is a very very simple html, without a full set of features and can't handle javascript etc. etc. Do you have a large team and years free in which to write what would effectively be your own browser.
EDIT:
You still keep talking about parsing as if parsing is the same thing as displaying it.
If you just want to display the http page at the url use UIWebView. The UIWebView will parse it AND display it. There's no need for you to parse it yourself. Or launch Safari from you app (but you won't be able to return to your app afterwards).
You say you can't use UIWebView? Why not?
To actually try and parse and display the HTML page yourself would be madness.

What does loadHTMLString:baseURL:

I new to iOS programming and tried to figure out what loadHTMLString:baseURL: really does, but I can't find a satisfying explanation. The site of Apple just says:
Sets the main page content and base URL.
Can someone please explain this in a more detailed way to me?
I am pretty certain that the baseURL is used just like in regular web pages to properly load ressources that are referenced using relative links. Now the question is, how to set that base URL to a particular folder in the app directory.
This is how mainly content is loaded in a webView. either from a local html file or through a url.
//this is to load local html file. Read the file & give the file contents to webview.
[webView loadHTMLString:someHTMLstring baseURL:[NSURL URLWithString:#""]];
//if webview loads content through a url then
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]]]
- (void) loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
is used to load local HTML file, parameter string means content of html file, if your HTML file contains some href tag with relative path, you should set the parameter baseUrl with the base address of the HTML file, or set it nil.
NSString *cachePath = [self cachePath];
NSString *indexHTMLPath = [NSString stringWithFormat:#"%#/index.html", cachePath];
if ([self fileIsExsit:indexHTMLPath]) {
NSString *htmlCont = [NSString stringWithContentsOfFile:indexHTMLPath
encoding:NSUTF8StringEncoding
error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:cachePath];
[self.webView loadHTMLString:htmlCont baseURL:baseURL];
}
- (NSString *)cachePath
{
NSArray* cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
return [cachePath[0] stringByAppendingPathComponent:#"movie"];
}

Check if it exists an app that can open a file before calling presentOpenInMenuFromRect

I have stored a file (pdf) in the "documents" directory and I would like to know how could be possible to detect if there are applications (app) installed in the mobile device that can open this file (for example, "pdf" files can be opened using "iBooks", "DropBox", ...). I would like to detect this before calling the method "presentOpenInMenuFromRect"; which shows a list of the possible applications that can handle a specific file. The desired behavior is:
1) Given a pdf stored in the "Document" directory, check if there are "app's" installed in the iPhone/iPad, which can open this file (iBooks, DropBox, ...). This is what I do not know how to do.
2) If no application in de iPhone/iPad can open the application, then do nothing, otherwise draw a "Save" button and then, if the user presses this "Save" button, then the "presentOpenInMenuFromRect" method will be called in order to show a list of possible app which can open that file. I know the way to present a list of of applications which can open a file; here are the source code:
The source code related to the "Save" button is:
- (void) saveFile:(UIWebView*)webView
{
NSString* fileName = [[NSFileManager defaultManager] displayNameAtPath:webView.request.URL.absoluteString];
#if DEBUG
NSLog(#"<%p %#: %s line:%d> File name:%#", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __PRETTY_FUNCTION__, __LINE__, fileName);
#endif
NSURL* fileurl = [NSURL URLWithString:webView.request.URL.absoluteString];
NSData* data = [NSData dataWithContentsOfURL:fileurl];
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* docsDirectory = [paths objectAtIndex:0];
NSString* filePath = [docsDirectory stringByAppendingPathComponent:fileName];
[data writeToFile:filePath atomically:YES];
NSURL* url = [NSURL fileURLWithPath:filePath];
//UIDocInteractionController API gets the list of devices that support the file type
docController = [UIDocumentInteractionController interactionControllerWithURL:url];
[docController retain]; //Very important, if "retain" is not called, the application crashes
//Present a drop down list of the apps that support the file type,
//clicking on an item in the list will open that app while passing in the file.
BOOL isValid = [docController presentOpenInMenuFromRect:CGRectZero inView:webView animated:YES]; //Using "webView" instead of "self.view"
if (!isValid)
{
[self showAlertSaveFileError:fileName]; //Shows an alert message
}
}
Thanks in advance.
Note: The response time of calling the method "presentOpenInMenuFromRect" is about several seconds, so this is the reason why I would like to know if there is a another way to detect and get a list of possible app installed on the mobile device which can open a specific file (pdf, ...)
Check out ihasapp.
http://www.ihasapp.com/
it says that it is an iOS framework that lets developers detect apps that are currently installed on their users' devices.

iphone email link not selected correctly

I'm creating a link to open my App and pass some data in the URL.
When I add the query parameter ? my link get broken.
NSData *fileData = [NSData dataWithContentsOfFile:dataFilePath];
NSString *encodedString = [GTMBase64 stringByWebSafeEncodingData:fileData padded:YES];
NSString *urlString = [NSString stringWithFormat:#"myApp://localhost/backup?%#",
encodedString];
the link is quite long, but also a shorter one doesn't work:
myApp://localhost/backup?PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48bG9jPjxpbmdyZWRpZW50VHlwZS
and when the e-mail appears in the iPhone, only this is underlined and act as a link:
myApp://localhost/
Adding the query as NeilInglis suggest it doesn't work also, the link is broken at same place.
NSString *urlString = [NSString stringWithFormat:#"myApp://localhost/backup?query=%#",
encodedString];
The Html is ON or OFF, it doesn't affect.
If I enocode the URL it also doesn't work ...
Don't know what I can try next ...
any ideas ?
thanks ...
regards,
r.
Try mapping the query parameter to a name.
#"myApp://localhost/backup?queryParamName=%#

NSString's stringByAppendingPathComponent: removes a '/' in http://

I've been modifying some code to work between Mac OS X and iPhone OS.
I came across some code that was using NSURL's URLByAppendingPathComponent: (added in 10.6), which as some may know, isn't available in the iPhone SDK.
My solution to make this code work between OS's is to use
NSString *urlString = [myURL absoluteString];
urlString = [urlString stringByAppendingPathComponent:#"helloworld"];
myURL = [NSURL urlWithString:urlString];
The problem with this is that NSString's stringByAppendingPathComponent: seems to remove one of the /'s from the http:// part of the URL.
Is this intended behaviour or a bug?
Edit
Ok, So I was a bit too quick in asking the question above. I re-read the documentation and it does say:
Note that this method only works with file paths (not, for example, string representations of URLs)
However, it doesn't give any pointers in the right direction for what to do if you need to append a path component to a URL on the iPhone...
I could always just do it manually, adding a /if necessary and the extra string, but I was looking to keep it as close to the original Mac OS X code as possible...
I would implement a myURLByAppendingPathComponent: method on NSURL that does the same thing. The reason to give it a different name is so it doesn't override the Apple-provided method when Apple gets around to porting the 10.6 API to the iPhone (so the "my" is just an example — the point is that it's unlikely somebody else would write a method with that name).
It seems to me you just want to mess with the path rather than the whole URL. Here's an untested example:
- (NSURL *)myURLByAppendingPathComponent:(NSString *)component {
NSString *newPath = [[self path] stringByAppendingPathComponent:component];
return [[[NSURL alloc] initWithScheme: [self scheme]
host: [self host]
path: newPath]
autorelease];
}
It would only work correctly with URLs that have file-like paths, but I'm pretty sure the Apple method works the same way. At any rate, hopefully it helps you in the right direction.
URLByAppendingPathComponent
Since iOS 4, URLByAppendingPathComponent is available on iOS and handles the two slashes correctly. (OS X had it since 10.6., as Chuck points out)
myURL = [myURL URLByAppendingPathComponent:#"hello world"]
// http://foo/bar/hello%20world
Note that unlike stringByAppendingPathComponent, this method escapes the argument.
URLWithString:relativeToURL:
Alternatively, there is URLWithString:relativeToURL:, which does not escape. So if the url component is already escaped, use:
myURL = [NSURL URLWithString:#"hello%20world" relativeToURL:myURL]
// http://foo/bar/hello%20world
Note that myURL needs to end with a slash here and the added segment must not have a leading slash.
The NSString Reference says this about stringByAppendingPathComponent:
Note that this method only works with
file paths (not, for example, string
representations of URLs).
So, I think it's a case of "Don't Do That".
Use -stringByAppendingString: instead?
There is a simple work around.
Using [NSString stringWithFormat:#"%#/%#", server, file] works fine.
E.g. server : ftp://www.server.com and file : file.txt
+ (NSString *)urlStringPathWithComponents:(NSArray *)paths
{
NSString *url = #"";
for( NSString *item in paths)
{
if([item isEqualToString:paths.firstObject])
{
url = [url stringByAppendingString:[NSString stringWithFormat:#"%#", item]];
}else{
url = [url stringByAppendingString:[NSString stringWithFormat:#"/%#", item]];
}
}
return url;
}
As you see the code above is a class method and this permit use in anywhere without a instance of an object.
Note: Always the first object of the array must be a base url.