Browse Source

【分包下载】XML版本

lizhe 1 year ago
parent
commit
78963e22db

+ 292 - 0
PDF Office/PDF Master/Class/KMResourceDownload/KMResourceDownloadManager.swift

@@ -6,9 +6,301 @@
 //
 
 import Cocoa
+import Foundation
+import ZipArchive // 请确保已导入 SSZipArchive 或其他合适的解压库
+
+let xmlURLString = "http://test-pdf-pro.kdan.cn:3021/downloads/DocumentAI.xml"
+let documentAIString = "http://test-pdf-pro.kdan.cn:3021/downloads/DocumentAI.bundle.zip"
+
+let kResourcePath = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first?.path
+
+enum KMResourceDownloadState {
+    case none
+    case unzipFailed
+    case moveFailed
+    case success
+}
 
 class KMResourceDownloadManager: NSObject {
     static let manager = KMResourceDownloadManager()
     
+    var downloadTask: URLSessionDownloadTask?
+    var progressBlock: ((Double) -> Void)?
+    var downloadResultBlock: ((Bool, KMResourceDownloadState) -> Void)?
+    
+    
+    func downloadFramework(progress: @escaping (Double) -> Void, result: @escaping (Bool, KMResourceDownloadState) -> Void) {
+        self.progressBlock = progress
+        self.downloadResultBlock = result
+        
+        if self.downloadTask == nil {
+            self.downloadXML { [unowned self] content in
+                let urlString = self.dealXML(content: content)
+    //            let urlString = "http://test-pdf-pro.kdan.cn:3021/downloads/DocumentAI.bundle.zip"
+                if let url = URL(string: urlString) {
+                    let configuration = URLSessionConfiguration.default
+                    let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
+                    let downloadTask = session.downloadTask(with: url)
+                    downloadTask.resume()
+                    self.downloadTask = downloadTask
+                } else {
+                    dealDownloadResult(isSuccess: false, state: .none)
+                }
+            }
+        } else {
+            dealDownloadResult(isSuccess: false, state: .none)
+        }
+    }
+    
+    func documentAIBundleExists() -> Bool {
+        let filePath: String = kResourcePath! + "/DocumentAI.bundle"
+        let fileManager = FileManager.default
+        let exists = fileManager.fileExists(atPath: filePath as String)
+        if exists {
+            self.checkDocumentAIVersion()
+        }
+        return exists
+    }
+    
+    func cancelDownload() {
+        downloadTask?.cancel()
+        downloadTask = nil
+        progressBlock = nil
+        downloadResultBlock = nil
+    }
+    
+    //结果处理
+    func dealDownloadResult(isSuccess: Bool, state: KMResourceDownloadState) {
+        DispatchQueue.main.async {
+            self.downloadResultBlock?(isSuccess, state)
+            self.cancelDownload()
+        }
+    }
+    
+    func checkDocumentAIVersion() {
+        self.downloadXML { [unowned self] content in
+            let urlString = self.dealXML(content: content)
+            if urlString.count != 0 {
+                let filePath: String = kResourcePath! + "/DocumentAI.bundle"
+                try?FileManager.default.removeItem(atPath: filePath)
+            }
+        }
+    }
+}
+
+extension KMResourceDownloadManager: XMLParserDelegate {
+    func downloadXML(completion: @escaping (_ content: String) -> Void) {
+        // 将 URL 字符串转换为 URL 对象
+        if let xmlURL = URL(string: xmlURLString) {
+            // 创建一个 URL 请求
+            let request = URLRequest(url: xmlURL)
+            // 创建一个 URLSession
+            let session = URLSession.shared
+            // 创建一个数据任务来下载 XML 数据
+            let task = session.dataTask(with: request) { (data, response, error) in
+                if let error = error {
+                    // 处理下载错误
+                    print("Error: \(error)")
+                } else if let data = data {
+                    // 成功下载 XML 数据
+                    if let xmlString = String(data: data, encoding: .utf8) {
+                        // 将 XML 数据打印出来(你可以进一步处理它,比如解析它)
+                        print("XML Data: \(xmlString)")
+                        completion(xmlString)
+                    }
+                }
+            }
+            
+            // 启动任务
+            task.resume()
+        } else {
+            // URL 字符串无效,进行错误处理
+            print("Invalid URL")
+            completion("")
+        }
+    }
+    
+    func dealXML(content: String) -> String {
+        // 1. 定义 XML 内容,包括版本号
+        let xmlContent = """
+        <root>
+            <version>1.0</version>
+            <resourceURL>http://test-pdf-pro.kdan.cn:3021/downloads/DocumentAI.bundle.zip</resourceURL>
+        </root>
+        """
+
+        // 2. 创建目标文件夹(如果不存在的话)
+        let fileManager = FileManager.default
+        let folderURL = fileManager.temporaryDirectory.appendingPathComponent("XMLResources")
+        try? fileManager.createDirectory(at: folderURL, withIntermediateDirectories: true, attributes: nil)
+
+        // 3. 将 XML 内容写入文件
+        let xmlURL = folderURL.appendingPathComponent("TempDocumentAI.xml")
+        try? xmlContent.write(to: xmlURL, atomically: true, encoding: .utf8)
+
+        // 4. 解析 XML 并比较版本号
+        // 创建 XMLParser 实例
+        var downloadedVersion = "1.0"
+        if let xmlData = try? Data(contentsOf: self.fetchXMLURL()) {
+            let xmlParser = XMLParser(data: xmlData)
+            let xmlDelegate = XMLDelegate()
+            xmlParser.delegate = xmlDelegate
+            
+            if xmlParser.parse() {
+                downloadedVersion = xmlDelegate.version ?? "1.0"
+            }
+        }
+                
+        if let xmlData = try? Data(contentsOf: xmlURL) {
+            let xmlParser = XMLParser(data: xmlData)
+            let xmlDelegate = XMLDelegate()
+            xmlParser.delegate = xmlDelegate
+            
+            if xmlParser.parse() {
+                // Parsing was successful
+                if let xmlVersion = xmlDelegate.version {
+                    if xmlVersion > downloadedVersion {
+                        // 下载资源的逻辑
+                        let resourceURL = xmlDelegate.resourceURL
+                        print("Download resource from \(resourceURL)")
+                        return resourceURL ?? ""
+                    } else {
+                        print("No need to download resources. Already up to date.")
+                    }
+                }
+            } else {
+                // Parsing failed
+            }
+        } else {
+            // Error handling for loading XML data
+        }
+        return ""
+    }
+    
+    func fetchXMLURL() -> URL {
+        // 2. 创建目标文件夹(如果不存在的话)
+        let fileManager = FileManager.default
+        let folderURL = fileManager.temporaryDirectory.appendingPathComponent("XMLResources")
+        try? fileManager.createDirectory(at: folderURL, withIntermediateDirectories: true, attributes: nil)
+
+        // 3. 将 XML 内容写入文件
+        let xmlURL = folderURL.appendingPathComponent("DocumentAI.xml")
+        return xmlURL
+    }
+    
+    func writeXML(content: String) {
+        let xmlURL = self.fetchXMLURL()
+        try? content.write(to: xmlURL, atomically: true, encoding: .utf8)
+    }
+    
+    func xmlResourceDownloadSuccess() {
+        let fileManager = FileManager.default
+        let folderURL = fileManager.temporaryDirectory.appendingPathComponent("XMLResources")
+        let xmlURL = folderURL.appendingPathComponent("DocumentAI.xml")
+        let tempXmlURL = folderURL.appendingPathComponent("TempDocumentAI.xml")
+        try?fileManager.removeItem(at: xmlURL)
+        
+        do {
+           // 尝试更改文件名称
+            try fileManager.moveItem(atPath: tempXmlURL.path, toPath: xmlURL.path)
+           print("文件重命名成功:\(xmlURL.path)")
+        } catch {
+           // 处理重命名失败的错误
+           print("文件重命名失败:\(error)")
+        }
+    }
+}
+
+extension KMResourceDownloadManager {
+    //MARK: 解压
+    func unzipFramework(at zipURL: URL, to destinationPath: String) {
+        let fileManager = FileManager.default
+        var success = false
+
+        if zipURL.pathExtension == "zip" {
+            success = SSZipArchive.unzipFile(atPath: zipURL.path, toDestination: destinationPath)
+        } else {
+            // 如果是其他类型的压缩文件,可以使用其他解压库
+            // success = YourCustomUnzipLibrary.unzipFile(atPath: zipURL.path, toDestination: destinationPath)
+        }
+        
+        if success {
+            print("File unzipped successfully!")
+            try? fileManager.removeItem(at: zipURL)
+        } else {
+            print("Failed to unzip file.")
+            dealDownloadResult(isSuccess: false, state: .unzipFailed)
+        }
+    }
+    
+    func loadFramework(destinationPath: String) {
+        let fileManager = FileManager.default
+        let bundlePath = destinationPath + "/DocumentAI.bundle"
+        
+        if fileManager.fileExists(atPath: bundlePath) {
+            if let bundle = Bundle(path: bundlePath) {
+                // 使用 framework 中的代码和资源
+                // 例如:bundle.load()
+                print("Framework loaded successfully!")
+            } else {
+                print("Error loading bundle.")
+                dealDownloadResult(isSuccess: false, state: .none)
+            }
+        } else {
+            dealDownloadResult(isSuccess: false, state: .none)
+        }
+    }
+}
+
+extension KMResourceDownloadManager: URLSessionDelegate, URLSessionDownloadDelegate {
+    //MARK: 网络下载
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
+        let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
+        print("Download progress: \(progress)")
+        progressBlock?(progress)
+    }
+    
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
+        guard let destinationPath = kResourcePath else {
+            return
+        }
+        
+        let fileManager = FileManager.default
+        let destinationURL = URL(fileURLWithPath: destinationPath).appendingPathComponent("DocumentAI.bundle.zip")
+        
+        do {
+            try fileManager.moveItem(at: location, to: destinationURL)
+            print("Framework downloaded and installed successfully!")
+            unzipFramework(at: destinationURL, to: destinationPath)
+            dealDownloadResult(isSuccess: true, state: .success)
+            self.xmlResourceDownloadSuccess()
+        } catch {
+            print("Failed to move framework: \(error)")
+            dealDownloadResult(isSuccess: false, state: .moveFailed)
+        }
+    }
+}
+
+
+// 5. 定义一个 XML 解析器的代理类
+class XMLDelegate: NSObject, XMLParserDelegate {
+    var currentElement: String = ""
+    var version: String?
+    var resourceURL: String?
+    
+    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
+        currentElement = elementName
+    }
     
+    func parser(_ parser: XMLParser, foundCharacters string: String) {
+        if currentElement == "version" {
+            if version == nil {
+                version = string
+            }
+        } else if currentElement == "resourceURL" {
+            if resourceURL == nil {
+                resourceURL = string
+            }
+        }
+    }
 }

+ 5 - 5
PDF Office/PDF Master/Class/PDFTools/Convert/View/KMConvertOCRSettingItemView.swift

@@ -78,7 +78,7 @@ class KMConvertOCRSettingItemView: KMConvertBaseView {
     
     @objc func checkBoxAction(sender: NSButton) {
 #if VERSION_DMG
-        let isExist = KMResourceDownload.manager().documentAIBundleIsExist()
+        let isExist = KMResourceDownloadManager.manager.documentAIBundleExists()
         if isExist || self._checkVC?.state == .Checked {
             if let state = self._checkVC?.state {
                 self._checkVC?.state = state == .Checked ? .Norm : .Checked
@@ -97,9 +97,9 @@ class KMConvertOCRSettingItemView: KMConvertBaseView {
                         self.showProgressWindow()
                         self.progressController?.maxValue = Double(100)
                     }
-                    KMResourceDownload.manager().downloadFrameworkProgress { progress in
+                    KMResourceDownloadManager.manager.downloadFramework(progress: { progress in
                         self.progressController?.doubleValue = Double(progress*100)
-                    } result: { result, downloadState  in
+                    }, result: { result, downloadState  in
                         if result {
                             if let state = self._checkVC?.state {
                                 self._checkVC?.state = state == .Checked ? .Norm : .Checked
@@ -114,7 +114,7 @@ class KMConvertOCRSettingItemView: KMConvertBaseView {
                             self._checkAction()
                         }
                         self.hiddenProgressWindow()
-                    }
+                    })
                 } else if result == .alertSecondButtonReturn {
                     return
                 }
@@ -151,7 +151,7 @@ class KMConvertOCRSettingItemView: KMConvertBaseView {
         
         progress.closeBlock = { [unowned self] in
 #if VERSION_DMG
-            KMResourceDownload.manager().cancel()
+            KMResourceDownloadManager.manager.cancelDownload()
 #endif
         }