【问题标题】:WKWebView save pdf to ibooks, save pdf from linkWKWebView 将 pdf 保存到 ibooks,从链接保存 pdf
【发布时间】:2025-12-26 08:40:11
【问题描述】:

我是 Junior,目前正在从事我在 WKWebView 中的项目,并且有打开 pdf 的链接。我可以在 Safari 中打开它,然后在 iBooks 中打开它,但我希望它在我的应用程序中完成。是否可以 ?

下面是它的样子:

我可以选择pdf的图片

想象一下它会打开什么

我的网络视图类

class WebVC: UIViewController, WKUIDelegate {



var webView: WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()
    let myURL = NSURL(string: "\(savedURL!)")
    let myRequest = URLRequest(url: myURL! as URL)
    webView.load(myRequest)
    webView.allowsBackForwardNavigationGestures = true
    webView.allowsLinkPreview = false
}

override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.toolbar.isHidden = false
}

override func loadView() {
    let webConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: CGRect(x: 100, y: 100, width: 110, height: 110), configuration: webConfiguration)
    webView.uiDelegate = self
    view = webView

}

@IBAction func logoutPressed(_ sender: AnyObject) {
    defaults.set(false, forKey: "isLogged")
    defaults.set("EMPTY URL", forKey: "savedURL")
    _ = self.navigationController?.popToRootViewController(animated: true)
}


@IBAction func goBack(_ sender: Any?) {
    if (self.webView.canGoBack) {
        self.webView.goBack()
    }
}

}

【问题讨论】:

    标签: ios swift pdf webview wkwebview


    【解决方案1】:
    • 在 webview 中打开 pdf

      //第一步

      webview.uiDelegate = self
      

      //第 2 步 - 实现委托函数(此函数将让您在 webview 中打开任何点击的 pdf)

      func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
      
           // open in current view
           webView.load(navigationAction.request)
           // don't return a new view to build a popup into (the default behavior).
           return nil;
       }
      
    • 下载

    在我的情况下,一旦我在 webview 中打开了 pdf,我就有了下载按钮,我用它来下载当前打开的 pdf

    //第 3 步 - 委托函数

        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            decisionHandler(WKNavigationActionPolicy.allow)
        }
        //find the mimeTime of the current url opened in webview, If it's pdf, we'll give option to download 
        func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
            
            if let mimeType = navigationResponse.response.mimeType {
                //check if mime exists in our acceptable mimes list
                if self.isMimeTypeConfigured(mimeType) {
                    self.mime = mimeType
                    self.currentUrl = navigationResponse.response.url
                    addDownloadButton()
                }
            }
            decisionHandler(.allow)
        }
    

    //第 4 步 - 使用辅助函数创建扩展

    //=== PDF downloading ===
    struct MimeType {
        var type:String
        var fileExtension:String
    }
    extension DownloadManual {
        //button
        private func addDownloadButton(){
            let btn = UIBarButtonItem(image: UIImage(systemName: "tray.and.arrow.down.fill"), style: .plain, target: nil, action: #selector(downloadTapped))
            self.navigationItem.rightBarButtonItem = btn
        }
        @objc func downloadTapped(){
            self.showActivityIndicator(show: true)
            if let url = currentUrl {
                print("download from: \(url)")
                let filename = getDefaultFileName(forMimeType: self.mime)
                
                downloadData(fromURL: url, fileName: filename) { success, destinationURL in
                    if success, let destinationURL = destinationURL {
                        
                        self.showActivityIndicator(show: false)
                        print("download result: \(success), \(destinationURL)")
                        self.fileDownloadedAtURL(url: destinationURL)
                    }
                }
            }
        }
        
        //helper funcs
        private func isMimeTypeConfigured(_ mimeType:String) -> Bool {
            for record in self.mimeTypes {
                if mimeType.contains(record.type) {
                    return true
                }
            }
            return false
        }
        
        func fileDownloadedAtURL(url: URL) {
            print("downloaded at: \(url)")
            DispatchQueue.main.async {
                let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
                activityVC.popoverPresentationController?.sourceView = self.view
                activityVC.popoverPresentationController?.sourceRect = self.view.frame
                activityVC.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
                self.present(activityVC, animated: true, completion: nil)
            }
        }
        private func downloadData(fromURL url:URL,
                                  fileName:String,
                                  completion:@escaping (Bool, URL?) -> Void) {
            webview.configuration.websiteDataStore.httpCookieStore.getAllCookies() { cookies in
                let session = URLSession.shared
                print("downloading ....")
                session.configuration.httpCookieStorage?.setCookies(cookies, for: url, mainDocumentURL: nil)
                let task = session.downloadTask(with: url) { localURL, urlResponse, error in
                    if let localURL = localURL {
                        let destinationURL = self.moveDownloadedFile(url: localURL, fileName: fileName)
                        completion(true, destinationURL)
                    }
                    else {
                        completion(false, nil)
                    }
                }
    
                task.resume()
            }
        }
        private func getDefaultFileName(forMimeType mimeType:String) -> String {
            for record in self.mimeTypes {
                if mimeType.contains(record.type) {
                    return "default." + record.fileExtension
                }
            }
            return "default"
        }
        
        private func moveDownloadedFile(url:URL, fileName:String) -> URL {
            let tempDir = NSTemporaryDirectory()
            let destinationPath = tempDir + fileName
            let destinationURL = URL(fileURLWithPath: destinationPath)
            try? FileManager.default.removeItem(at: destinationURL)
            try? FileManager.default.moveItem(at: url, to: destinationURL)
            return destinationURL
        }
    

    希望这对某人有帮助:)

    【讨论】:

      【解决方案2】:

      我用 UIDocumentInteractionController 解决了这个问题,添加一个按钮,当我按下按钮时,它将下载整个页面,然后在“导入到 iBooks”选项所在的位置显示 DocumentController。希望对您有所帮助。

      @IBAction func shareBtn(_ sender: AnyObject) {
          var localPath: NSURL?
      
          Alamofire.download(webView.url!, method: .get, parameters: nil, headers: nil) { (tempUrl, response)  in
      
              let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
              let pathComponent = response.suggestedFilename
      
              localPath = directoryURL.appendingPathComponent(pathComponent!) as NSURL?
              return (destinationURL: localPath as! URL, options: .removePreviousFile)
      
      
              }.response { response in
                  if localPath != nil{
      
      
                      self.docController = UIDocumentInteractionController(url: localPath! as URL)
                      self.docController.presentOptionsMenu(from: sender as! UIBarButtonItem, animated: true)
      
                  }
          }
      }
      

      【讨论】:

      • 这将再次下载PDF,有什么方法可以使用从WKWebView加载的PDF。