// // KMURLToPDF.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/10/16. // import Cocoa import WebKit import PDFKit class KMURLToPDF: NSObject, WKNavigationDelegate { @objc public static let shareInstance = KMURLToPDF() var webView: WKWebView! var completion: ((URL?, Error?) -> Void)? var savePath: String = "" var saveName: String = "" func convertHtmlFileToPDF(fromPath: String, toPath: String, completion: @escaping (URL?, Error?) -> Void) { self.completion = completion savePath = toPath webView = WKWebView(frame: CGRectMake(0, 0, 1920, 1080)) webView.navigationDelegate = self let fileURL: URL = URL(fileURLWithPath: fromPath) let readAccessURL = fileURL.deletingLastPathComponent() webView.loadFileURL(fileURL, allowingReadAccessTo: readAccessURL) saveName = fromPath.deletingPathExtension.lastPathComponent + ".pdf" } func convertLinkString(string: String, toPath: String, completion: @escaping (URL?, Error?) -> Void) { self.completion = completion savePath = toPath webView = WKWebView(frame: CGRectMake(0, 0, 1920, 1080)) webView.navigationDelegate = self if let url = URL(string: string) { webView.load(URLRequest(url: url)) } } func stopLoading() { webView?.stopLoading() } //MARK: - WKNavigationDelegate func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { webView.stopLoading() let configuration: WKPDFConfiguration = WKPDFConfiguration() var contentWidth: CGFloat = 0 var contentHeight: CGFloat = 0 webView.evaluateJavaScript("document.title") { (result, error) in if let name = result as? String { self.saveName = name + ".pdf" } webView.evaluateJavaScript("document.body.scrollWidth") { (width, error) in if let width = width as? CGFloat { contentWidth = width } // 获取内容高度 webView.evaluateJavaScript("document.body.scrollHeight") { (height, error) in if let height = height as? CGFloat { contentHeight = height } if contentWidth > 0 && contentHeight > 0 { configuration.rect = CGRectMake(0, 0, contentWidth, contentHeight) webView.createPDF(configuration: configuration) { result in switch result { case .success(let pdfData): // PDF successfully created, handle the PDF data let filePath = URL(fileURLWithPath: self.savePath.stringByAppendingPathComponent(self.saveName)) if FileManager.default.fileExists(atPath: filePath.path) { try?FileManager.default.removeItem(atPath: filePath.path) } do { try pdfData.write(to: filePath) print("PDF saved to: \(filePath)") } catch { print("Failed to save PDF: \(error)") } guard let callBack = self.completion else { return } callBack(filePath, nil) case .failure(let error): guard let callBack = self.completion else { return } callBack(nil, error) } } } else { guard let callBack = self.completion else { return } callBack(nil, NSError(domain: "create error", code: 0)) } } } } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { webView.stopLoading() guard let callBack = self.completion else { return } callBack(nil, error) } func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { webView.stopLoading() guard let callBack = self.completion else { return } callBack(nil, error) } }