[英]How to download files from inside WKWebview on macOS
so I'll keep it short.所以我会保持简短。 AS the title says I have an a web view embedded in my SwiftUI application for macOS and there's a link on the website which downloads a.doc file.
正如标题所说,我的 SwiftUI 应用程序中嵌入了一个 web 视图,并且网站上有一个下载 a.doc 文件的链接。 However WKWebView doesn't really let you know download stuff from the internet like that.
然而,WKWebView 并没有真正让你知道从互联网上下载东西。 I looked around SO and there are a few ways to solve it but none of them pertain to SwiftUI.
我环顾四周,有几种方法可以解决它,但没有一个与 SwiftUI 相关。 Does anyone know how can I simply download a normal text file from a website onto the Mac using WKWebView in SwiftUI?
有谁知道如何使用 SwiftUI 中的 WKWebView 将普通文本文件从网站下载到 Mac 上?
Here's my WebView code:这是我的 WebView 代码:
import SwiftUI
import WebKit
import Combine
class WebViewData: ObservableObject {
@Published var loading: Bool = false
@Published var url: URL?;
var popupWebView: WKWebView?
init (url: URL) {
self.url = url
}
}
@available(OSX 11.0, *)
struct WebView: NSViewRepresentable {
@ObservedObject var data: WebViewData
func makeNSView(context: Context) -> WKWebView {
return context.coordinator.webView
}
func updateNSView(_ nsView: WKWebView, context: Context) {
guard context.coordinator.loadedUrl != data.url else { return }
context.coordinator.loadedUrl = data.url
if let url = data.url {
DispatchQueue.main.async {
let request = URLRequest(url: url)
nsView.load(request)
}
}
context.coordinator.data.url = data.url
}
func makeCoordinator() -> WebViewCoordinator {
return WebViewCoordinator(data: data)
}
}
@available(OSX 11.0, *)
class WebViewCoordinator: NSObject, WKNavigationDelegate {
@ObservedObject var data: WebViewData
var webView: WKWebView = WKWebView()
var loadedUrl: URL? = nil
init(data: WebViewData) {
self.data = data
super.init()
webView.navigationDelegate = self
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
DispatchQueue.main.async {
self.data.loading = false
}
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
DispatchQueue.main.async { self.data.loading = true }
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError. error: Error) {
showError(title: "Navigation Error", message: error.localizedDescription)
DispatchQueue.main.async { self.data.loading = false }
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
showError(title: "Loading Error", message: error.localizedDescription)
DispatchQueue.main.async { self.data.loading = false }
}
func showError(title: String, message: String) {
#if os(macOS)
let alert: NSAlert = NSAlert()
alert.messageText = title
alert.informativeText = message
alert.alertStyle = .warning
alert.runModal()
#else
print("\(title): \(message)")
#endif
}
}
Here's my Content View这是我的内容视图
import SwiftUI
@available(OSX 11.0, *)
struct ContentView: View {
private var url: URL? = URL(string: "https://mywebsite.com")
init() {
print("Hello World")
}
var body: some View {
WebView(data: WebViewData(url: self.url!))
.frame(minWidth: 1400, idealWidth: 1500, minHeight: 850, idealHeight: 850)
}
}
Also here's how my website downloads the files using JS in case anyone's interested:另外,如果有人感兴趣,我的网站如何使用 JS 下载文件:
function exportworddocument(){
var sourceHTML = document.getElementById("notes").innerHTML;
var source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
var fileDownload = document.createElement("a");
document.body.appendChild(fileDownload);
fileDownload.href = source;
var lines = $('#notes').val().split('.');//gives all lines
const firstLine=lines[0];
console.log(firstLine)
fileDownload.download = firstLine + ".doc";
fileDownload.click();
document.body.removeChild(fileDownload);
}
We have to implement some of the decision policy callbacks as WKNavigationDelegate
, like我们必须将一些决策策略回调实现为
WKNavigationDelegate
,例如
// early decision per URL
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.request.url?.pathExtension == "doc" {
decisionHandler(.download)
} else {
decisionHandler(.allow)
}
}
// when known response
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if navigationResponse.response.mimeType == "your type" {
decisionHandler(.download)
} else {
decisionHandler(.allow)
}
}
Have your WebViewCoordinator
implement WKDownloadDelegate
so it can handle a WKDownload
.让您的
WebViewCoordinator
实现WKDownloadDelegate
以便它可以处理WKDownload
。 Implement webView(_:decidePolicyFor:decisionHandler:)
to call decisionHandler(.download)
for the files you want to download, and then implement download(_:decideDestinationUsing:suggestedFilename:completionHandler:)
to choose the download destination for a given request.实现
webView(_:decidePolicyFor:decisionHandler:)
为您要下载的文件调用decisionHandler(.download)
,然后实现download(_:decideDestinationUsing:suggestedFilename:completionHandler:)
为给定请求选择下载目的地。
A more expansive answer to a similar question is available at How to download files in wkwebview , and there's a good blog post on the topic at: http://www.gfrigerio.com/download-files-in-a-wkwebview/ How to download files in wkwebview提供了对类似问题的更广泛的答案,并且有一篇关于该主题的很好的博客文章: http://www.gfrigerio.com/download-files-in-a-wkwebview/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.