如何从WKWebView拦截PDF链接并保存至iOS Files应用的Downloads文件夹?
嗨,作为Swift新手能找到那个可行的方案已经超棒啦!你想要把PDF存到Files应用的公共Downloads文件夹,只需要调整文件保存的目标路径,同时确保共享面板能正确指向这个位置就行。下面是具体的实现步骤和代码:
实现步骤
1. 配置WKWebView并拦截PDF链接
首先确保你的WKWebView设置了navigationDelegate,这样才能拦截页面里的PDF链接:
class YourViewController: UIViewController, WKNavigationDelegate { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let webConfig = WKWebViewConfiguration() webView = WKWebView(frame: view.bounds, configuration: webConfig) webView.navigationDelegate = self webView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(webView) // 加载目标网站 if let targetURL = URL(string: "你的目标网站地址") { webView.load(URLRequest(url: targetURL)) } }
接着实现拦截逻辑,判断链接是否为PDF并接管打开操作:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let requestURL = navigationAction.request.url else { decisionHandler(.allow) return } // 检查是否是PDF链接(通过后缀判断,也可以根据MIME类型优化) if requestURL.pathExtension.lowercased() == "pdf" { downloadAndSharePDF(from: requestURL) decisionHandler(.cancel) // 拦截原网页的打开操作 } else { decisionHandler(.allow) // 其他链接正常跳转 } }
2. 下载PDF并保存到系统Downloads文件夹
这一步是核心:我们不再把文件存到应用私有的Documents目录,而是存到系统级的公共Downloads文件夹,这样用户就能在Files应用里直接找到它。
private func downloadAndSharePDF(from url: URL) { // 启动URLSession下载PDF数据 URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let self = self, let pdfData = data, error == nil else { print("PDF下载失败:\(error?.localizedDescription ?? "未知错误")") return } // 获取系统公共Downloads文件夹的路径 guard let downloadsDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first else { print("无法访问系统Downloads文件夹") return } // 用原链接的文件名作为保存的文件名,避免重名也可以自己生成 let fileName = url.lastPathComponent let savePath = downloadsDirectory.appendingPathComponent(fileName) do { // 将PDF数据写入Downloads文件夹 try pdfData.write(to: savePath) // 回到主线程弹出共享面板(UI操作必须在主线程执行) DispatchQueue.main.async { self.presentSharePanel(for: savePath) } } catch { print("保存PDF失败:\(error.localizedDescription)") } }.resume() }
3. 调出共享面板
实现共享面板的弹出逻辑,用户可以选择“保存到文件”(默认会指向Downloads文件夹),也可以选择其他共享方式:
private func presentSharePanel(for fileURL: URL) { let activityViewController = UIActivityViewController( activityItems: [fileURL], applicationActivities: nil ) // 适配iPad的popover展示(如果你的App支持iPad) if let popoverPresenter = activityViewController.popoverPresentationController { popoverPresenter.sourceView = self.view popoverPresenter.sourceRect = CGRect( x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0 ) popoverPresenter.permittedArrowDirections = [] } // 弹出共享面板 present(activityViewController, animated: true) } }
4. 配置Info.plist权限
最后别忘了在Info.plist里添加权限描述,否则iOS会拒绝你的App访问Downloads文件夹:
添加Privacy - Downloads Folder Usage Description(键名:NSDownloadsFolderUsageDescription),并填写一段友好的说明,比如:
需要保存PDF到Downloads文件夹,方便你在Files应用中随时查看和管理
关键说明
- 系统的
Downloads文件夹是所有App都能访问的公共目录,用户在Files应用的“浏览”标签下就能找到它; - 共享面板里的“保存到文件”选项默认会定位到Downloads文件夹,用户也可以手动选择其他位置;
- 所有UI操作(比如弹出共享面板)必须在主线程执行,所以我们用
DispatchQueue.main.async切换回主线程。
内容的提问来源于stack exchange,提问作者Joshua Lowe
相关产品推荐
相关产品推荐

