简体   繁体   中英

iOS: WKWebview how to allow html file located in bundle read access to documents directory

I have an html file located in a bundle and I'm using WKWebView to load content from this html:

let fileURL = URL(fileURLWithPath: Bundle.main.path(forResource:"demo", ofType: "html")!)
    webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL)

However, this html file have some scripts which are trying to get access to files located in Documents dir (some videos saved in there) but get a "can't load local resources." error. I'm using this files somewhere else in AVPlayerViewController so I know the files exists and the url I'm using is the right one.

I tried:

1. pass the documents dir url to the allowingReadAccessTo parameter - the webview doesn't even load

2. Copy the items from documents dir to tmp dir and passing this (tmp dir) url in the scripts - it works , but this process happens too much and I don't want to copy so many files due to memory issues and the time it take for big files.

3. Copy the html file and its scripts from the bundle to documents dir - not relevant because the scripts Im using changes from time to time, so to make sure the user always have the last version (of the scripts) I will have to copy it every time the app launches.

So, is there any other way to allow html file (located in bundle) access the documents file?

Thanks in advance,

This covers one file, but you should be able to build a function that copies the relevant files to the Documents Directory using the code below.

///Copy the file from the bundle to the Documents Directory
guard let bundleURL = Bundle.main.url(forResource:"demo", ofType: "html") else {
     preconditionFailure("Unable to get bundle URL") 
}

guard let documentsDirectory = let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
     preconditionFailure("Unable to get Documents URL") 
}

let newURL = documentsDirectory.appendingPathComponent("demo.html")

do {
   try FileManager.default.copyItem(at: bundleURL, to: newUrl)
} catch {
   print("Error copying bundle: \(error)")
}


///Setup the WKWebView
let prefs = WKPreferences()
prefs.javaScriptEnabled = true

let webConfig = WKWebViewConfiguration()
webConfig.preferences = prefs

var webViewer = WKWebView(frame: view.frame, configuration: webConfig)
webViewer.loadFileURL(newURL, allowingReadAccessTo: documentsDirectory)

Keep in mind, the Bundle is located in a different directory altogether within your app. Just because the file has access to the Documents Directory does not mean that the HTML within the file will be able to find the referencing scripts or other HTML files you're referencing. You should consider everything within the bundle to be immutable and the location itself a source origin only.

This is a little old now but in case anyone else is having this issue, I was having the exact same problem after finally updating from UIWebView to WKWebView . It seems to be related to the new security enhancements of WKWebView . Oddly enough, I was only experiencing issues on my real device and not on the simulator.

Basically, I had an html template file in the main app bundle, and then in my code I would load the html file in a WKWebView (after my code replaced some placeholders with URLs to user-created images stored in FileManager.documentDirectory() . The html file would load in the WKWebView , but the images were blank white squares.

Using loadFileURL(_:allowingReadAccessTo:) seems to allow the HTML file to access the user images stored in documentDirectory :

  if let docDirectory = FileManager.documentDirectory() {
    do {
      let bundleHtmlTemplateURL = URL(fileURLWithPath: bundleHtmlTemplatePath)
      // I'm guessing the below line resolves the supposed security / access issue
      self.webView.loadFileURL(bundleHtmlTemplateURL, allowingReadAccessTo: docDirectory)
    
      self.webView.loadHTMLString(htmlContents, baseURL: docDirectory)
      
      let contents = try FileManager.default.contentsOfDirectory(at: docDirectory, includingPropertiesForKeys: nil, options: [])
      // do other stuff
    } catch {
      print("error loading pdf preview")
  }
}

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM