How can I load file with hash with WKWebview - ios

I use the code to load URL path hash fragment (such as: index.html#/some-hash-path; but WKWebview not load url.
let path = "www/index.html"
let page = "#/some-hash-path"
let url = Bundle.main.bundleURL.appendingPathComponent(path + page)
self.webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
It seem that it convert # -> %23 which make invalid path

I got stuck too trying to build the url in an apparently correct way for local files.
The url must be created with URL(string:) initializer, prefixing it manually with file://, and loaded with loadFileURL().
let url = URL(string: "file://\(indexPath)#\(section)")
webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)

Construct URL from string work as expected:
let path = "www/index.html"
let page = "#/some-hash-path"
guard let parsedUrl = URL(string: Bundle.main.bundleURL.absoluteString + path + page) else {
return
}
self.webView.loadFileURL(parsedUrl, allowingReadAccessTo: Bundle.main.bundleURL)

Related

Unable to convert string to URL in Swift iOS

In order to make HTTP request call using URLSession,I need to convert string to URL first so I have tried everything but just can’t convert this piece of string to URL(string: ).
This is the string:
“http://api-aws-eu-qa-1.abc-cde.com/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99”
I can’t share the exact Url but format is all same.
The actual url with same format works fine in browser but no way in Swift, also that works fine in POSTMAN
I have also tried URLComponents which hepls me create the URL from components to URL but that fails with 400 status code response error.
I really appreciate the help, I am completely bogged down with this isuue and can’t proceed with my assignment.
Update: Tested with fiddler and request was not going through with this URL - "“http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99”"
But when removed this %E2%80%8B in fiddler and resend it worked.
Any thoughts ..?
String to URL
let url = URL(string: "the url string goes here")
URL to String
let url = URL(string: "the url string goes here")
let urlString = url.absoluteString
Creating URL from URLComponents
var url: URL? {
var components = URLComponents()
components.scheme = "https"
components.host = "domain goes here" //example: twitter.com
components.path = "/path/goes/here"
components.queryItems = [
URLQueryItem(name: "item1", value: string1),
URLQueryItem(name: "item2", value: string2)
]
return components.url
}
try to add HEADER to you request:
let url = URL(string : urlString)
var request = URLRequest(url : url)
request.setValue("Application/json", forHTTPHeaderField : "Content-Type")
Your URL is:
http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99`
The "host" portion is:
api-aws-eu-qa-1.abc-cde.com%E2%80%8B
%E2%80%8B encodes a ZERO WIDTH SPACE. This is a perfectly valid URL:
URL(string: "http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")
=> Optional(http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99)
However, there is no such host as api-aws-eu-qa-1.abc-cde.com%E2%80%8B, so you should expect the actual connection to fail.
I expect that whatever is generating your URL strings has a bug.
If you are having trouble creating the URL itself (if URL(string:) return nil, then I expect this is not your actual URL string.
If you construct an URLComponents, the results are correct but may be slightly misleading:
URLComponents(string: "http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")?.host
Optional("api-aws-eu-qa-1.abc-cde.com")
While this looks like "api-aws-eu-qa-1.abc-cde.com", the string actually has a ZERO WIDTH SPACE at the end, which is invisible (but still part of the host field, which will correctly fail if you try to connect to it).

Web View Not loading with url request and URL show nil

I want to load web view with linkedin authorization url but before loading url was not created stating that it was nil and web view not show any specific page.
This is the url string that was passed to URLRequest.
https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=*******&redirect_uri=****&state=linkedin1575812567&scope=r_liteprofile
below mention is the code for that.
let responseType = "code"
let state = "linkedin\(Int(NSDate().timeIntervalSince1970))"
var authorizationURL = "\(authorizationEndPoint)?"
authorizationURL += "response_type=\(responseType)&"
authorizationURL += "client_id=\(linkedInConfig.linkedInKey)&"
authorizationURL += "redirect_uri=\(linkedInConfig.redirectURL)&"
authorizationURL += "state=\(state)&"
authorizationURL += "scope=\(scope)"
print(authorizationURL)
let url = URL(string: authorizationURL)
let request = URLRequest(url: url!)
webView.load(request)
URLs can only contain a certain set of characters. Using other characters can cause such errors. Or even the allowed characters can also sometimes cause this, for example, an '&' is used as a delimiter and cannot be directly used in a URL query parameter value.
You can use this for encoding those chaotic characters :
let newURL = YOUR_URL.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let url = URL(string: newURL)

Issue deep linking to MS Excel from iOS app

I am trying to open an Excel document that is located on a server. I wrote the following code but it always returns false for UIApplication.shared.canOpenURL(url as URL)
I think I am missing some requirement for deep linking to Excel. Why is iOS not able to understand ms-excel:ofe|u| format?
#objc static func openExcel() {
let originalString = "http://s000.tinyupload.com/download.php?file_id=23290165129849240725&t=2329016512984924072514118"
let encodedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let encodedURLString = "ms-excel:ofe|u|" + encodedString! + "|n|TestDoc.xlsx|a|App"
if let url = NSURL(string: encodedURLString),
UIApplication.shared.canOpenURL(url as URL) {
UIApplication.shared.openURL(url as URL)
} else if let itunesUrl = NSURL(string: "https://itunes.apple.com/us/app/microsoft-excel/id586683407?mt=8&uo=4"), UIApplication.shared.canOpenURL(itunesUrl as URL) {
UIApplication.shared.openURL(itunesUrl as URL)
}
}
I have analyzed your code and found some mistakes. First, your URL was redirecting to somewhere, as per Microsoft documentation it can't handle redirecting URL's
The URL has to be encoded and must be a direct link to the file (not a
redirect). If the URL is in a format that Office cannot handle, or the
download simply fails, Office will not return the user to the invoking
application.
Here is Microsoft Documentation Link
The second mistake was you are only encoding the URL string containing site URL, you should consider the part after the scheme ms-excel: as a URL and should be encoded.
Because of improper encoding the let url = URL(string: encodedURLString) results nil that's why it is not working as expected.
Here is an example working code:
#objc static func openExcel() {
//replace the below url with yours. may be this one dosen't work
let originalString = "ofe|u|https://pgcconline.blackboard.com/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx"
let encodedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let encodedURLString = "ms-excel:" + encodedString!
if let url = URL(string: encodedURLString),
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.openURL(url)
} else if let itunesUrl = NSURL(string: "https://itunes.apple.com/us/app/microsoft-excel/id586683407?mt=8&uo=4"), UIApplication.shared.canOpenURL(itunesUrl as URL) {
UIApplication.shared.openURL(itunesUrl as URL)
}
}
Note: From iOS 9 you must whitelist any URL schemes your App wants to query in Info.plist under the LSApplicationQueriesSchemes key (an array of strings):
For example in our case:
When i try to open the URL in the question above I get redirected to this URL, so my guess would be that your code is fine, it just might be that your excel file you're trying to open is really an HTML page since tinyupload apparently blocks direct links to the files.
Maybe try opening a direct excel file download link, https://pgcconline.blackboard.com/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx (it was the first google result for 'xlsx file sample download')

NSURLConnection finished with error - code -1002 when trying to encode URL in iOS

I was trying to encode a URL. The code works fine when I encode files in my bundle. But when I tried to encode the files written to Documents and Cache, the program fails to encode.
Here is my encoder:
private class func EncodeURL(_ url:URL,encoding:UInt) ->String {
do{
return try NSString(contentsOf: url, encoding: encoding) as String
}catch{}
return ""
}
I'm using the following three:
content = EncodeURL(url, encoding: String.Encoding.utf8.rawValue)
content = EncodeURL(url, encoding: 0x80000632)
content = EncodeURL(url, encoding: 0x80000631)
And none of them work.
Here is the code I use to generate files. I'm putting them in the Documents Folder.
func writeFile(fileName:String,data:NSData)->Bool{
guard let filePath = createFilePath(fileName: fileName) else{
return false
}
return data.write(toFile:filePath,atomically:true)
}
func createFilePath(fileName:String)->String?{
let dir = getCachePath()
if(!dirExists(dir: dir) && !createDir(dir: dir)){
return nil
}
let filePath = dir + fileName
if(fileExists(path: filePath)){
do{
try getFileManager().removeItem(atPath: filePath)
}catch{
return nil
}
}
return filePath
}
func getCachePath()->String{
var cacheDir = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, .userDomainMask, true).first!
if(!cacheDir.hasSuffix("/")){
cacheDir += "/"
}
cacheDir += CACHEPATH + "/" //CACHEPATH is just NSHomeDirectory()
return cacheDir
}
writeFile(fileName: String(timeInterval)+"_"+somestring+".txt", data: data! as NSData)
Above is how I generate the files.
And how I passed URL is:
url = URL(string:getCachePath()+bookname+".txt")
passing this to
EncodeURL(url:URL,encoding:UInt)
My URL is:
/Users/houki/Library/Developer/CoreSimulator/Devices/67C921C8-18A3-4A3F-81FF-C3AF04E88049/data/Containers/Data/Application/85633861-90E6-4DB8-95B0-86C359C74C6B/Documents//Users/houki/Library/Developer/CoreSimulator/Devices/67C921C8-18A3-4A3F-81FF-C3AF04E88049/data/Containers/Data/Application/85633861-90E6-4DB8-95B0-86C359C74C6B/1511757881.83107_bigbrother.txt
Does this look weird? I'm testing it on a simulator though.
But actually this worked just fine when I tried to read files through the path. The following code is working.
let contentsofPath = try FileManager.default.contentsOfDirectory(atPath: getCachePath())
You are not creating your URL correctly. You are passing a path to the string argument. You need to use the URL(fileURLWithPath:) initializer.
let url = URL(fileURLWithPath: path)
Only use the URL(string:) initializer if the string you pass is a valid URL beginning with a URL scheme.
For anyone still looking for a solution on Objective-C,
If you are trying to access the bundle file, to create NSURL you'll have to use
fileURLWithPath
instead
URLWithString
.
Usually, -1002 error suggests, the URI is invalid.
For Objective-C, below can be the code -
NSURL *url = [NSURL fileURLWithPath:resourceURL];
later, you can utilize this URI in your code.
It could also be because your url is not https
Add this in your plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
or get the secure version of http url
This worked for me. A simple Single view app running on iphone 6s simulator gave error 1022 until I added Allow Arbitrary loads. my url was not local to Iphone, but to an external url though. Thanks

Use AFNetworking to download a file from Django server

I am using AFNetworking to send a HTTP request to a Django server to download a file to iPhone. However, neither do the console print out "Success" or "Error". I also cannot find the file in the specific dir ".../database". For the server side, the log file is correct ([22/Jan/2015 16:45:49] "GET /main/receivefile/ HTTP/1.1" 200 16811) and I can see the request and there is no error. This is my client side code:
var parameters = ["username":"u987103"];
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let outPath = String(format: "%#/database/tmp.txt", documentsPath)
self.man = AFHTTPRequestOperationManager()
self.op = self.man.GET(url, parameters: parameters,
success: {(operation:AFHTTPRequestOperation!,responseObject:AnyObject!) in
println("Success")
}
, failure:{(operation:AFHTTPRequestOperation!,error:NSError!) in
println("Error: %#",error);
})
op.outputStream = NSOutputStream(toFileAtPath: outPath, append: false)
The code corresponding to the request URL in the Django server is:
def retrieve_file(request):
filename = os.path.basename(m_path)
path = os.path.join(settings.MEDIA_ROOT,m_path)
wrapper = FileWrapper(file(path))
response = HttpResponse(wrapper,content_type="text/plain")
response['Content-Disposition'] = 'attachment; filename="'+filename+'"'
return response
I have tested to download the file using Chrome and as soon as I enter the URL and hit "enter", the file is downloaded to my download folder. So could anyone tell me why it does not work for AFNetwokring?
Yes that is correct.
Take a look at the doc here - http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPRequestOperationManager.html#//api/name/responseSerializer. You need to specify a response serializer for AFHttpRequestOperationManager.
It seems like you are downloading a plain text file, so you can use the default serializer. Add this call:
self.man.responseSerializer = AFHttpResponseSerializer()
before you call self.man.GET.
The https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide has some details on how the response and request serializers work.
The code below is the correct way to do it for AFNetwokring 2.5.0
Reference: http://cocoadocs.org/docsets/AFNetworking/2.5.0/
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var man = AFURLSessionManager(sessionConfiguration: configuration)
var URL = NSURL(string: "http://www.google.com/images/srpr/logo11w.png")
var request = NSURLRequest(URL:URL!)
var downloadTask = man.downloadTaskWithRequest(request, progress: nil,
destination:{(targetPath:NSURL!,response:NSURLResponse!) -> NSURL! in
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let outPath = String(format: "%#/download/", documentsPath)
var url:NSURL! = NSURL(fileURLWithPath: outPath)
return url.URLByAppendingPathComponent(response.suggestedFilename as String!)
},
completionHandler:{(response:NSURLResponse!,filePath:NSURL!,error:NSError!) in
println(response.suggestedFilename)
})
downloadTask.resume();

Resources