WKWebView xmlhttprequest with file url

WKWebView xmlhttprequest with file url

本文关键字:url file with xmlhttprequest WKWebView      更新时间:2023-09-26

我正在使用应用程序文档文件夹中的本地HTML从UIWebView迁移到WKWebView。我可以使用所有 css 和 js 文件加载索引页,但是由于允许访问源,每个 ajax 调用 (xmlhttprequest) 都失败了。

我不想在我的应用程序中使用 Web 服务器,因为我认为它会过大。我怎样才能实现它?该应用程序是一个简单的HTML5应用程序,用于内部应用程序。该设备无法上网或无法在线,因此可以完全禁用安全性。

这解决了我的问题:

let config = WKWebViewConfiguration()
config.userContentController = contentController
config.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webView = WKWebView(frame: .zero, configuration: config)
webView.uiDelegate = self
webView.navigationDelegate = self
view = webView

对于那些通过SO找到这个话题的人:

这不是关闭WKWebView安全性的官方,但是我们可以使用私有API来允许这样做,就像这个人为Cordova项目所做的那样:cordova-plugin-wkwebviewxhrfix

线索是为 Web 视图创建配置并设置 allowFileAccessFromFileURL 属性。

WKWebViewConfiguration* configuration = originalImpSend(_self, selector, settings);
// allow access to file api
@try {
    [configuration.preferences setValue:@TRUE forKey:@"allowFileAccessFromFileURLs"];
}
@catch (NSException *exception) {}
@try {
    [configuration setValue:@TRUE forKey:@"allowUniversalAccessFromFileURLs"];
}
@catch (NSException *exception) {}
return configuration;

但正如我所提到的,这是私有API,这可能是在Apple的应用程序评论中拒绝您的应用程序的原因。如果您想在App Store中发布您的应用程序,请考虑运行一些轻量级HTTP服务器,而不是违反Web视图的整体安全性。示例:GCDWebServer。

因此,当我第一次尝试时,接受的内容对我不起作用(当时我做错了),并且关于(https://bugs.webkit.org/show_bug.cgi?id=154916)的错误强烈建议不要这样做。 我的解决方案是实现一个自定义 url 方案并使用它来加载所有文件。 看起来像这样。

首先创建 url 方案附加到的 WKWebView

(您必须自己创建 WKWebView,它不能在情节提要上创建)。

override func viewDidLoad() {
    let configuration = WKWebViewConfiguration()
    configuration.setURLSchemeHandler(PrayerAssetHandler(), forURLScheme: "x-file")
    webview = WKWebView(frame: webContentView.bounds, configuration: configuration)
    self.webContentView.addSubview(webview!)
    webview?.autoresizingMask = webContentView.autoresizingMask
    webview!.navigationDelegate = self
    super.viewDidLoad()
}

然后实现处理程序。

import Foundation
import WebKit
import MobileCoreServices
class PrayerAssetHandler: NSObject, WKURLSchemeHandler {
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        let url = urlSchemeTask.request.url!
        let pathArr = url.path.components(separatedBy: ".")
        let forResource: String = pathArr[0]
        let ofType: String? = pathArr.count > 1 ? pathArr[1] : nil
        let bundlePath = Bundle.main.path(forResource: "data_sub_folder" + forResource, ofType: ofType)
        let fileExtension: CFString = ofType! as CFString
        guard
            let extUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
                                fileExtension, nil)?.takeUnretainedValue()
        else { return }
        guard
            let mimeUTI: NSString = UTTypeCopyPreferredTagWithClass(extUTI,
                                kUTTagClassMIMEType)?.takeRetainedValue()
        else { return }
        let mimeType: String = mimeUTI as String
        do {
            let data: Data = try NSData(contentsOfFile: bundlePath!) as Data
            //Create a NSURLResponse with the correct mimetype.
            let urlResponse = URLResponse(url: url, mimeType: mimeType,
                                          expectedContentLength: data.count, textEncodingName: "utf8")
            urlSchemeTask.didReceive(urlResponse)
            urlSchemeTask.didReceive(data)
            urlSchemeTask.didFinish()
        }  catch _ as NSError {
            return
        }
    }
    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
    }
}

在首选项中设置值在 Swift 5 中不起作用。在"WKWebViewConfiguration"中设置,如下所示。

// Configuration
let webConfiguration = WKWebViewConfiguration()
webConfiguration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webConfiguration.setValue(true, forKey: "allowUniversalAccessFromFileURLs")
// Web View
let webView = WKWebView(frame: webviewContainer.frame, configuration: webConfiguration)