Swift 4中为WKWebView添加PDF下载按钮及实现PDF下载至iPhone的方法咨询
实现WKWebView的PDF下载功能及添加下载按钮技巧
嘿,针对你用Xcode 9开发的WKWebView应用,这里有一套贴合你现有代码的方案,一步步搞定PDF下载和添加下载按钮的问题:
一、先完善WKWebView代理配置,拦截PDF请求
首先确保你的WKWebView已经绑定了navigationDelegate,在viewDidLoad里补充配置(如果还没加的话):
override func viewDidLoad() { super.viewDidLoad() webView.navigationDelegate = self // 保留你原有的activityIndicator、backButton等配置... }
接下来通过代理方法处理PDF相关请求,分两种场景:
场景1:拦截网页中的PDF下载链接
当用户点击网页里的PDF下载按钮/链接时,我们拦截请求自己处理下载:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let targetURL = navigationAction.request.url else { decisionHandler(.allow) return } // 判断请求目标是否为PDF文件 if targetURL.pathExtension.lowercased() == "pdf" { decisionHandler(.cancel) // 阻止WKWebView默认加载 self.downloadPDF(from: targetURL) // 调用自定义下载方法 } else { decisionHandler(.allow) // 其他请求正常放行 } }
场景2:检测当前加载的是PDF页面
如果网页直接嵌入显示PDF(比如URL本身就是PDF地址),我们在页面加载完成后显示下载按钮:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard let currentURL = webView.url else { return } if currentURL.pathExtension.lowercased() == "pdf" { // 在导航栏添加下载按钮 self.navigationItem.rightBarButtonItem = UIBarButtonItem( barButtonSystemItem: .download, target: self, action: #selector(downloadCurrentPDF) ) } else { // 非PDF页面隐藏下载按钮 self.navigationItem.rightBarButtonItem = nil } } @objc private func downloadCurrentPDF() { guard let pdfURL = webView.url else { return } self.downloadPDF(from: pdfURL) }
二、实现PDF下载与保存的核心逻辑
下面是downloadPDF(from:)方法,负责下载PDF到本地,并提供保存/分享选项:
private func downloadPDF(from url: URL) { // 显示加载提示 DispatchQueue.main.async { self.activityIndicator.startAnimating() } let session = URLSession(configuration: .default) let downloadTask = session.downloadTask(with: url) { [weak self] tempFileURL, response, error in guard let self = self, let tempURL = tempFileURL, error == nil else { DispatchQueue.main.async { self?.activityIndicator.stopAnimating() let alert = UIAlertController(title: "下载失败", message: error?.localizedDescription ?? "未知错误", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) } return } // 定义本地保存路径:Documents目录下以原文件名保存 let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileName = url.lastPathComponent let saveURL = documentsDir.appendingPathComponent(fileName) // 移动临时文件到目标路径 do { // 如果文件已存在,先删除旧文件 if FileManager.default.fileExists(atPath: saveURL.path) { try FileManager.default.removeItem(at: saveURL) } try FileManager.default.moveItem(at: tempURL, to: saveURL) DispatchQueue.main.async { self.activityIndicator.stopAnimating() // 弹出分享菜单,让用户选择保存到文件或其他APP let activityVC = UIActivityViewController(activityItems: [saveURL], applicationActivities: nil) self.present(activityVC, animated: true) } } catch { DispatchQueue.main.async { self.activityIndicator.stopAnimating() let alert = UIAlertController(title: "保存失败", message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self.present(alert, animated: true) } } } downloadTask.resume() }
三、可选:给PDF网页内部添加下载按钮
如果你想在PDF页面的网页内容里直接插入下载按钮,可以通过注入JavaScript实现:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard let currentURL = webView.url, currentURL.pathExtension.lowercased() == "pdf" else { return } // 注入JS代码,在页面右下角添加固定的下载按钮 let jsCode = """ var downloadBtn = document.createElement('button'); downloadBtn.textContent = '下载PDF'; downloadBtn.style.position = 'fixed'; downloadBtn.style.bottom = '20px'; downloadBtn.style.right = '20px'; downloadBtn.style.padding = '10px 20px'; downloadBtn.style.backgroundColor = '#007AFF'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '5px'; downloadBtn.style.zIndex = '9999'; downloadBtn.onclick = function() { window.webkit.messageHandlers.pdfDownload.postMessage('\(currentURL.absoluteString)'); }; document.body.appendChild(downloadBtn); """ webView.evaluateJavaScript(jsCode) { _, error in if let error = error { print("注入下载按钮失败:\(error)") } } }
然后需要提前配置WKWebView的消息处理器,接收JS的下载请求:
override func viewDidLoad() { super.viewDidLoad() let webConfig = WKWebViewConfiguration() // 添加消息处理器,用于接收网页JS的下载指令 webConfig.userContentController.add(self, name: "pdfDownload") // 初始化WKWebView(如果你的webView是代码创建的话) webView = WKWebView(frame: containerView?.bounds ?? .zero, configuration: webConfig) webView.navigationDelegate = self containerView?.addSubview(webView) // 保留你原有的其他配置... } // 实现WKScriptMessageHandler协议,接收JS消息 extension ViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "pdfDownload", let pdfURLString = message.body as? String, let pdfURL = URL(string: pdfURLString) { downloadPDF(from: pdfURL) } } }
四、注意事项
- 若你的APP访问HTTP链接,需要在Info.plist中添加
NSAppTransportSecurity配置,允许HTTP请求。 - 保存到Documents目录的PDF,用户可以通过系统“文件”APP找到你的APP目录查看。
- Xcode 9对应的最低iOS版本通常是iOS 11,上述方法完全兼容该版本及以上系统。
内容的提问来源于stack exchange,提问作者Mr White
相关产品推荐
相关产品推荐

