load html file from documents directory fails to include css files

I have an App which moves all HTML files to my own folder on the iPhone:

file:///var/mobile/Containers/Data/Application/AD332281-2ADE-4809-ABF2-F3FC3004AF42/Documents/MOTHER-APP/index.html

and:

file:///var/mobile/Containers/Data/Application/AD332281-2ADE-4809-ABF2-F3FC3004AF42/Documents/MOTHER-APP/css/mother.css


The problem is - when the App loads the index.html file into webview no CSS files are available.

I have tested if the index file and the CSS file exists and it is all there.

I have tried both:


webView.loadHTMLString(indexfile, baseURL: baseUrl)

and:

webView.loadFileURL(destinationURLForFile, allowingReadAccessTo: destinationURLForFile)


The HTML index file requests the CSS like this:

< link rel="stylesheet" type="text/css" href="css/mother.css" />

Accepted Reply

Ok, I retried with Documents dir urls, and this worked:

        let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let indexFileUrl = documentDirUrl.appendingPathComponent("index.html")
        webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)


Documents directory on simulator is diffrent from the real device, it's as usual.


How have you made those urls?


(Note: I have no entry for App Transport Security in the plist of my test project.)

Replies

Sorry, I was missing the part you are trying with your app's document directory. Just trying...

Hi, thanks for the reply, Your code does work if you are reading the index.html file from the Bundle directory, but i have coppied all my web files to my own directory, in the "Documents" folder


On device:

file:///var/mobile/Containers/Data/Application/AD332281-2ADE-4809-ABF2-F3FC3004AF42/Documents/MOTHER-APP/css/mother.css


The strange thing is on a simulator the App works perfectly but the path on the simulator is slightly different:

Simulator:

"file:///Users/mark/Library/Developer/CoreSimulator/Devices/67D744AA-6EEC-4AFD-A840-366F4D78A18C/data/Containers/Data/Application/DD96F423-AF9F-4F4D-B370-94ADE7D6D0A5/Documents/MOTHER-APP/css/mother.css

Thank you I have also tried adding this to the plist:



<key>NSAppTransportSecurity</key>

<dict>

<key>NSAllowsArbitraryLoads</key>

<true/>

<key>NSExceptionAllowsInsecureHTTPLoads</key>

<true/>

<key>NSExceptionMinimumTLSVersion</key>

<true/>

<key>NSExceptionRequiresForwardSecrecy</key>

<true/>

<key>NSIncludesSubdomains</key>

<true/>

</dict>

Ok, I retried with Documents dir urls, and this worked:

        let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let indexFileUrl = documentDirUrl.appendingPathComponent("index.html")
        webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)


Documents directory on simulator is diffrent from the real device, it's as usual.


How have you made those urls?


(Note: I have no entry for App Transport Security in the plist of my test project.)

Hi I think we are getting closer I have this now in the log:


****** Error *****

Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo={NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/CFD0B5A9-6BAD-43C4-BB0F-4393F48D46FD/Documents/index.html, NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/CFD0B5A9-6BAD-43C4-BB0F-4393F48D46FD/Documents/index.html, NSLocalizedDescription=The requested URL was not found on this server., NSUnderlyingError=0x14ecc1a0 {Error Domain=kCFErrorDomainCFNetwork Code=-1100 "The requested URL was not found on this server."

I have swapped your code for mine but my index.html is in "Documents/MOTHER-APP/"

Do you think it may be because of the /MOTHER-APP/ folder?


webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)


would it be because the only the documentsDirUrl has permission and not my MOTHER-APP folder?


I added:

let indexFileUrl = documentDirUrl.appendingPathComponent("/MOTHER-APP/index.html")

And now do not get the error just a black screen

My code assumes `index.html` and `css/mother.css` exist directly under the app's Document directory.

So, if you put those files under /MOTHER-APP/, my code needs a simple modification:

        let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("MOTHER-APP")
        let indexFileUrl = documentDirUrl.appendingPathComponent("index.html")


Try with these urls. (Assuming you have already created the directory and successfully copied all files required.)


`documentDirUrl`, which is passed to `allowingReadAccessTo:` also needs MOTHER-APP in its path.


In my environment (actual device),


documentDirUrl:

file:///var/mobile/Containers/Data/Application/1B63DBCD-E18A-4EB6-8A92-E88983C3BA23/Documents/MOTHER-APP/

indexFileUrl:

file:///var/mobile/Containers/Data/Application/1B63DBCD-E18A-4EB6-8A92-E88983C3BA23/Documents/MOTHER-APP/index.html

WO hOOO you are a genius, your code works!!!!


Tha black screen was just me being an ejot missed the add.subview


I have been trying to crack this for about 4 days

Happy to here that. May your app be great. Happy coding.

I had the same problem, your post solved it.


Worked on simulator, not on actual device iPad


        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let filePath = "\(documentsPath)/new.pdf"
        let url = URL(fileURLWithPath: filePath)
        print("url", url)
        let urlRequest = URLRequest(url: url as URL)
        webView.load(urlRequest)

url : file:///var/mobile/Containers/Data/Application/DEB48BD2-63BD-4011-AE4E-F0029C99F218/Documents/new.pdf


with your code, it works

        let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let indexFileUrl = documentDirUrl.appendingPathComponent("new.pdf")
        webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)

        print("indexFileUrl", indexFileUrl)

I get

indexFileUrl file:///var/mobile/Containers/Data/Application/506047E2-3BB1-4880-BE3C-564516C638B5/Documents/new.pdf


The only change is the folder which contains document. Means it is erroneous in the first case ?

The most important thing in my code is not the way how to get url or path, but using the method `loadFileURL(_:allowingReadAccessTo:)`.


In fact, the core part of WKWebView runs in a different process (or processes, maybe), which does not have read access to an app's Documents folder where it it Sandboxed.


In simulators, some part of macOS file system is simulated as an iOS devices file system, but the protection of Sandboxing is sort of loose and the process of WKWebView can access the Documents directory of the app.


`allowingReadAccessTo:` allows temprary read access to the WKWevView process (I do not know the detail, just that it works), so even in strictly Sandboxed environment, `loadFileURL(_:allowingReadAccessTo:)` would work as expected.

load Html WkWebView in Objective-c

I have an App that contains all .Html, .Css, JS files to my own folder on the iPhone and I just want to load that file into WkWebView in Objective-c

  1. Base Path: file:///var/mobile/Containers/Data/Application/B03D85C5-C269-4C7A-8DAF-/Library/DOWNLOADED_CONTENT/BUSINESSETIQUET/document/

Have files like index.html , bootstrap.min.css , index.css. , test.js , jquery.min.js



NSString *htmlString = @"<html>
<head>
    <script type="text/javascript" src="jquery.min.js"></script>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=2.5; user-scalable=YES"/>
    <meta http-equiv="Content-Type" content="text/html; accept-charset=UTF-8">
    <link rel="stylesheet" href="bootstrap.min.css">
    <link rel="stylesheet" href="index.css">
     <script type="text/javascript" src="j__test.js"></script>
    
</head>
<body>
    <div class="container">
        <img id="image" src="" class="img-responsive" style="height: auto;width: auto;margin: auto;display: block;" alt="Cinque Terre"/>
        <br>
        <div style="font-size: 2vw;margin: auto; line-height: 1.5;float: inherit;clear: both;">
            <label class="radio">
                <input type="checkbox" id="opt1" class="radio-hide" name="Option"/>
                &nbsp;
                <label for="opt1">
                    <span></span>
                </label>
                <div style="max-width: 75%;min-width: auto;display: inline-table;text-align:left; ">
                    <font size="3" face="agency_fb">Helps conceal body language.</font>
                </div>
            </label>
            </b>
            <br>
            <center>
                <input type="button" name="button" id="actionButtonID" value="Submit" style="background-color:#5380C1">
            </center>
        </div>
    </div>
</body>
</html>";



NSString *contentPath = @"file:///var/mobile/Containers/Data/Application/B03D85C5-C269-4C7A-8DAF-/Library/DOWNLOADED_CONTENT/myCourses/document/index.html";

NSURL *baseURL = [NSURL fileURLWithPath:contentPath];

[wkWebView loadHTMLString:htmlString baseURL:baseURL];

It works in iOS 14.x but not in iOS 12.X. Did you also experience this problem?