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

WKWebView加载Angular应用时无法下载jsPDF生成的PDF问题求助

解决WKWebView中Angular应用jsPDF下载无响应的问题

这个问题很常见——WKWebView不像Safari那样自带下载处理逻辑,当你的Angular应用用jsPDF触发下载时,WebView不知道该怎么处理这个请求,所以才会出现控制台没输出但下载无响应的情况。下面给你两种可行的解决方案,你可以根据自己的iOS版本需求选择:

方案一:通过WKNavigationDelegate接管下载任务(iOS 13+)

从iOS 13开始,WKWebView提供了直接处理下载任务的代理方法,我们可以用它来捕获jsPDF触发的下载请求,然后把PDF保存到本地并提供分享选项:

  1. 首先更新你的ViewController代码,添加WKNavigationDelegate协议并设置代理:
import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    @IBOutlet var mWebKit: WKWebView!
    let url = URL(string: "foo.bar")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mWebKit.uiDelegate = self
        // 必须设置navigationDelegate才能接收下载回调
        mWebKit.navigationDelegate = self
        
        let request = URLRequest(url: url!)
        mWebKit.load(request)
    }
    
    // 当下载任务完成时调用
    func webView(_ webView: WKWebView, downloadTask: WKDownloadTask, didFinishDownloadingTo location: URL) {
        // 读取下载的PDF数据
        guard let pdfData = try? Data(contentsOf: location) else {
            print("无法读取PDF数据")
            return
        }
        
        // 将PDF保存到应用的文档目录
        let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let saveURL = documentsDir.appendingPathComponent("generated.pdf")
        
        do {
            try pdfData.write(to: saveURL)
            // 弹出分享面板,让用户选择保存或分享PDF
            let shareVC = UIActivityViewController(activityItems: [saveURL], applicationActivities: nil)
            present(shareVC, animated: true)
        } catch {
            print("保存PDF失败:\(error.localizedDescription)")
        }
    }
    
    // 允许下载请求继续执行
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.shouldPerformDownload {
            decisionHandler(.allow)
        } else {
            decisionHandler(.allow)
        }
    }
}

方案二:通过JS与原生交互传递PDF数据(兼容所有iOS版本)

如果你的App需要支持iOS 12及以下版本,或者jsPDF是通过Blob URL触发的下载(这种情况方案一可能捕获不到),可以用JS把PDF的base64数据直接传给原生,再由原生处理保存:

原生代码修改:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKScriptMessageHandler {
    @IBOutlet var mWebKit: WKWebView!
    let url = URL(string: "foo.bar")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mWebKit.uiDelegate = self
        
        // 添加消息处理器,接收JS传来的PDF数据
        let userContentController = mWebKit.configuration.userContentController
        userContentController.add(self, name: "savePDF")
        
        let request = URLRequest(url: url!)
        mWebKit.load(request)
    }
    
    // 接收JS发送的消息
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard message.name == "savePDF", let pdfBase64 = message.body as? String else {
            print("无效的PDF数据")
            return
        }
        
        // 将base64转为Data
        guard let pdfData = Data(base64Encoded: pdfBase64) else {
            print("base64解码失败")
            return
        }
        
        // 保存并分享PDF,逻辑和方案一一致
        let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let saveURL = documentsDir.appendingPathComponent("generated.pdf")
        
        do {
            try pdfData.write(to: saveURL)
            let shareVC = UIActivityViewController(activityItems: [saveURL], applicationActivities: nil)
            present(shareVC, animated: true)
        } catch {
            print("保存PDF失败:\(error.localizedDescription)")
        }
    }
}

Angular前端代码修改:

把原来的doc.save()替换成向原生发送消息的代码:

// 生成PDF的代码不变,修改保存逻辑
const doc = new jsPDF();
doc.text("Hello World!", 10, 10);

// 将PDF转为base64并发送给原生
const pdfBase64 = doc.output('datauristring').split('base64,')[1];
if (window.webkit?.messageHandlers?.savePDF) {
    window.webkit.messageHandlers.savePDF.postMessage(pdfBase64);
}

注意事项

  • 如果你选择方案一,确保你的App部署目标是iOS 13或更高版本;
  • 保存文件到相册或其他系统目录时,需要在Info.plist中添加对应的权限描述(比如NSPhotoLibraryAddUsageDescription);
  • 先在桌面浏览器测试你的Angular应用,确保jsPDF能正常生成PDF,排除前端代码的问题。

内容的提问来源于stack exchange,提问作者Inbar Azulay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:26