IOS - 如何从WKWebView获取缓存资源?
IOS - How to get cached resources from WKWebView?
据我所知,WKWebView
中加载的所有资源的缓存是默认设置的。有几个 post 关于 How to remove cached resources from WKWebView? 但我找不到任何 post 关于从 [=11 获取它的方法=].
例如,当我使用 WKWebView
加载 this url 时,它显示一个 pdf 文件,我想要的是从 WKWebView
获取此 pdf 文件以在 [=42] 之后共享=] 已完全加载
我已经检查了 Chrome,如果我想从上面 link 共享文件,它会在显示共享对话框后再次从 url 请求和下载内容。这意味着他们无法从当前 WKWebView
(缓存的资源)中获取它。
但在 Safari 上,不知何故,他们在点击分享按钮后立即显示分享对话框,似乎没有再次下载。我认为他们从缓存或 WkWebView
中的某处获取 pdf 文件并共享它。
另一种理解问题的方法是How to get a file which presented on WKWebView without download content again?
如果问题没有足够的信息来回答,请随时发表评论,我会把它说得更清楚。
As I know, caching for the all resources loaded in WKWebView is set by
default: True
记住这一点,如果您请求相同的资源,webview 将不会从互联网加载内容,它会为您提供来自缓存资源的内容。对于请求相同的资源,可以使用一些JavaScript来获取内容。
看下面的代码。加载 PDF 后,您点击保存按钮。它将执行 JavaScript 代码,当数据准备好通过 JavaScript
交付时
它会触发 window.webkit.messageHandlers.myInterface.postMessage(base64)
让您的 ViewController 知道数据已准备好共享。
您可以通过
验证相同
让它加载 PDF
关闭模拟器的网络(see)
点击保存按钮
您将获得 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
}
}
顺便说一句,您提供的 pdf link 使用的是 HTTP 而不是 HTTPS。因此,出于测试目的,请在 info.plist
中添加以下内容
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
据我所知,WKWebView
中加载的所有资源的缓存是默认设置的。有几个 post 关于 How to remove cached resources from WKWebView? 但我找不到任何 post 关于从 [=11 获取它的方法=].
例如,当我使用 WKWebView
加载 this url 时,它显示一个 pdf 文件,我想要的是从 WKWebView
获取此 pdf 文件以在 [=42] 之后共享=] 已完全加载
我已经检查了 Chrome,如果我想从上面 link 共享文件,它会在显示共享对话框后再次从 url 请求和下载内容。这意味着他们无法从当前 WKWebView
(缓存的资源)中获取它。
但在 Safari 上,不知何故,他们在点击分享按钮后立即显示分享对话框,似乎没有再次下载。我认为他们从缓存或 WkWebView
中的某处获取 pdf 文件并共享它。
另一种理解问题的方法是How to get a file which presented on WKWebView without download content again?
如果问题没有足够的信息来回答,请随时发表评论,我会把它说得更清楚。
As I know, caching for the all resources loaded in WKWebView is set by default: True
记住这一点,如果您请求相同的资源,webview 将不会从互联网加载内容,它会为您提供来自缓存资源的内容。对于请求相同的资源,可以使用一些JavaScript来获取内容。
看下面的代码。加载 PDF 后,您点击保存按钮。它将执行 JavaScript 代码,当数据准备好通过 JavaScript
交付时它会触发 window.webkit.messageHandlers.myInterface.postMessage(base64)
让您的 ViewController 知道数据已准备好共享。
您可以通过
验证相同让它加载 PDF
关闭模拟器的网络(see)
点击保存按钮
您将获得 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
}
}
顺便说一句,您提供的 pdf link 使用的是 HTTP 而不是 HTTPS。因此,出于测试目的,请在 info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>