iOS-如何从WKWebView获取缓存的资源?

tru*_*duc 5 objective-c ios swift wkwebview

据我所知,WKWebView默认情况下会为所有加载的资源设置缓存。关于如何从WKWebView中删除缓存的资源有几篇文章?但我找不到有关从中获取信息的方法的任何帖子WKWebView。

例如,当我WKWebView用来加载此url时,它会显示一个pdf文件,而我要获取的WKWebView是在完全加载url之后共享此pdf文件

我已经在Chrome上进行了检查,如果我想从上面的链接共享文件,它将在显示共享对话框后再次请求并从url下载内容。这意味着他们不会从当前WKWebView(缓存的资源)中获取它。

但是在Safari上,它们以某种方式在单击“共享”按钮后立即显示“共享”对话框,并且看起来好像无需再次下载。我认为他们从缓存或其他地方获取pdf文件WkWebView并共享它。

理解该问题的另一种方法是如何获取在WKWebView上显示的文件而无需再次下载内容?

在此处输入图片说明

如果问题没有足够的答案信息,请随时发表评论,我将使其更加清楚。

Sah*_*nda 5

据我所知,WKWebView中加载的所有资源的缓存默认设置为:True

请记住,如果您请求相同的资源,webview 将不会从互联网加载内容,而是会为您提供缓存资源中的内容。为了请求相同的资源,您可以使用一些JavaScript来获取内容。

看下面的代码。加载 PDF 并点击“保存”按钮后。它将执行 JavaScript 代码,并且当数据准备好由 JavaScript 传递时

它会火window.webkit.messageHandlers.myInterface.postMessage(base64)

让您的 ViewController 知道数据已准备好共享。

您可以通过以下方式验证相同的内容

  1. 让它加载 PDF

  2. 关闭模拟器的互联网(参见)

  3. 点击保存按钮

您将获得 Base64 格式的 pdf 数据。保存并分享:)

    import UIKit
    import WebKit
    class ViewController: UIViewController {

        @IBOutlet weak var webView: WKWebView!
        var activityIndicator: UIActivityIndicatorView?
        override func viewDidLoad() {
            super.viewDidLoad()

        }

        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
            webView.navigationDelegate = self
            activityIndicator?.center = self.view.center
            self.view.addSubview(activityIndicator!)
            webView.configuration.userContentController.add(self, name: "myInterface")
            webView.load(URLRequest(url: URL(string: "http://www.africau.edu/images/default/sample.pdf")!))
            activityIndicator?.startAnimating()
        }

        @IBAction func saveAction(_ sender: Any) {
            let s = """
            var xhr = new XMLHttpRequest();
            xhr.open('GET', "\(webView.url?.absoluteString ?? "")", true);
            xhr.responseType = 'arraybuffer';
            xhr.onload = function(e) {
            if (this.status == 200) {
            var uInt8Array = new Uint8Array(this.response);
            var i = uInt8Array.length;
            var binaryString = new Array(i);
            while (i--){
            binaryString[i] = String.fromCharCode(uInt8Array[i]);
            }
            var data = binaryString.join('');
            var base64 = window.btoa(data);

       window.webkit.messageHandlers.myInterface.postMessage(base64);
            }
            };
            xhr.send();
            """




            webView?.evaluateJavaScript(s, completionHandler: {(string,error) in
                print(error ?? "no error")
            })
        }
    }

    extension ViewController: WKScriptMessageHandler{
      func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    //    print("Message received: \(message.name) with body: \(message.body)")

        guard
          var documentsURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last,
          let convertedData = Data.init(base64Encoded: message.body as! String)
          else {
            //handle error when getting documents URL
            return
        }

        //name your file however you prefer
        documentsURL.appendPathComponent("sample.pdf")

        do {
          try convertedData.write(to: documentsURL)
        } catch {
          //handle write error here
        }

        //if you want to get a quick output of where your
        //file was saved from the simulator on your machine
        //just print the documentsURL and go there in Finder
        print(documentsURL)

        let activityViewController = UIActivityViewController.init(activityItems: [documentsURL], applicationActivities: nil)
        present(activityViewController, animated: true, completion: nil)
      }
    }

    extension ViewController: WKNavigationDelegate{
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            self.activityIndicator?.stopAnimating()
            self.activityIndicator?.removeFromSuperview()
            self.activityIndicator = nil
        }
    }
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您提供的 pdf 链接使用的是 HTTP 而不是 HTTPS。因此,出于测试目的,在您的中添加以下内容info.plist

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
        <true/>
    </dict>
Run Code Online (Sandbox Code Playgroud)