You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:32:20