// // FileConverter.swift // KdanAuto // // Created by 朱东勇 on 2022/12/21. // import Foundation import ComPDFKit_Conversion import PDFKit let KMComPDFKit_Conversion_FreeKey = "hw5vIMzKU2Im6cPijLjG45VAHy01ikUF5/GdAMdzCV8n2QTKNN0d8kG8crVbGYjIMsvVP+A9gx5g+W8qEi4ho0YTkGDratHOrX68W7khEBHAv7OEyRxIhlhBmdEQD+21lsRpIEW5zucUAF231lo3ZZiiT2s9CualDQJdAo1G0DI="; let KMComPDFKit_Conversion_FreeSecret = "mG0c3O3Mzeu5dkZJW3gpqh188cTuhYlGRPrbR/gfX4p9ms/F1zY6gZ1RBu8mNJH8zLwqe9EJswNmwV09TNi2IiIDeG7Ulx+U4pbeFB3/eYl2J6LePb3Kl54OsKlYiaf3Mv7C2jvq4o0q6sQtN3jR4897KG6mIUGJSRuOsvjYroVgMwna6EUx0K0SBmBGoFYDYkwcNWVMyYvggPV2rTFvfawopGIC034QzjthmhwwX90="; let KMPDFConvertOptionsKeyImageDPI = "KMPDFConvertOptionsKeyImageDPI" let KMPDFConvertOptionsKeyImageWithAnnotation = "KMPDFConvertOptionsKeyImageWithAnnotation" let kDefaultPassword = "666666" class FileConverter : NSObject, CPDFConverterDelegate, CPDFConverterFPDelegate { var pdfConverter:CPDFConverter? var fpConverter:CPDFConverterFP? var options:CPDFConvertOptions? var originSrcPath:String = "" var srcPath:String = "" var desPath:String = "" var pages:[Int] = [] var pathExtension = "" var convertQueue = DispatchQueue.main var semaphore:DispatchSemaphore? = DispatchSemaphore.init(value: 0) var accessSemaphore:DispatchSemaphore? = DispatchSemaphore.init(value: 1) var didSuccess:Int = 1 let m_currentVersion = CPDFConvertKit.sharedInstance().buildNumber var complention = { (status:Int) in } static var instance = FileConverter() class func shared() -> FileConverter { return instance } func converter(_ inSrcPath: String, inDesPath: String, complention:@escaping (_ status:Int) -> ()) { return converter(inSrcPath, inDesPath: inDesPath, params: nil, complention: complention) } func converter(_ inSrcPath: String, inDesPath: String, params:NSDictionary?, complention:@escaping (_ status:Int) -> ()) { self.complention = complention; if !FileManager.default.fileExists(atPath: inSrcPath) { self.complention(-1) return } self.originSrcPath = inSrcPath; self.srcPath = inSrcPath self.desPath = inDesPath if FileManager.default.fileExists(atPath: desPath) { try? FileManager.default.removeItem(atPath: desPath) } let directory = NSString(string: desPath).deletingLastPathComponent if !FileManager.default.fileExists(atPath: directory) { try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true) } let attributy = try! FileManager.default.attributesOfItem(atPath: srcPath) let fileType = attributy[FileAttributeKey.type] as! FileAttributeType if NSString(string: FileAttributeType.typeSymbolicLink.rawValue).isEqual(to: fileType.rawValue) { let symbolicLink = try? FileManager.default.destinationOfSymbolicLink(atPath: self.srcPath) if nil != symbolicLink { self.srcPath = symbolicLink! } } if FileManager.default.fileExists(atPath: self.desPath) { try? FileManager.default.removeItem(atPath: self.desPath) } self.pathExtension = NSString(string: self.desPath).pathExtension // let outputPath = NSString(string: self.desPath).deletingPathExtension // let output = self.desPath let password = params?.value(forKey: "password") let tParams = params ?? [:] let useOldLibValue = params?.value(forKey: "useOldLib") var useOldLib = false; if (nil != useOldLibValue) { if ((useOldLibValue as? String) != nil) { useOldLib = NSArray(array: ["TRUE", "true", "1"]).contains((useOldLibValue as! String)) }else if ((useOldLibValue as? NSNumber) != nil) { useOldLib = (useOldLibValue as? NSNumber)!.boolValue || (useOldLibValue as? NSNumber)!.intValue == 1 } } // NSLog("%@ - %@\n\(inSrcPath)", useOldLib ? "老库" : "新库", params ?? "") self.convertQueue.async { let url = URL.init(fileURLWithPath: self.srcPath, isDirectory: false) let document = PDFDocument(url: url) if document == nil { self.didSuccess = -2; self.accessSemaphore?.signal() return } let pageCount = document!.pageCount self.pages = [] for i in 1...pageCount { self.pages.append(i) } if !useOldLib && NSArray(array: ["jpg", "JPG", "png", "PNG"]).contains(self.pathExtension) { autoreleasepool { let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip" self.pdfConverter = CPDFConverterImg.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterImg.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertImgOptions() if (NSArray(array: ["jpg", "JPG"]).contains(self.pathExtension)) { (self.options as! CPDFConvertImgOptions).type = .JPEG }else { (self.options as! CPDFConvertImgOptions).type = .PNG } self.configForOptions(self.options, inParams: tParams); do { try? self.pdfConverter?.convert(toFilePath: cachePath, pageIndexs: self.pages, options: self.options) }catch { self.didSuccess = -1; self.complention(self.didSuccess) } } }else if !useOldLib && NSArray(array: ["ppt", "PPT", "PPTX", "pptx"]).contains(self.pathExtension) { autoreleasepool { self.pdfConverter = CPDFConverterPPT.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterPPT.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertPPTOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: self.desPath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["doc", "DOC", "docx", "DOCX"]).contains(self.pathExtension) { autoreleasepool { self.pdfConverter = CPDFConverterWord.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterWord.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertWordOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: self.desPath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["xls", "XLS", "xlsx", "XLSX"]).contains(self.pathExtension) { autoreleasepool { self.pdfConverter = CPDFConverterExcel.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterExcel.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertExcelOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: self.desPath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["csv", "CSV"]).contains(self.pathExtension) { autoreleasepool { let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip" self.pdfConverter = CPDFConverterCsv.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterCsv.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertCsvOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: cachePath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["html", "HTML"]).contains(self.pathExtension) { autoreleasepool { let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip" self.pdfConverter = CPDFConverterHtml.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterHtml.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertHtmlOptions() // if ((tParams.value(forKey: "paneOptions") as? NSNumber) != nil) { // (self.options as! CPDFConvertHtmlOptions).paneOptions = CPDFConvertHtmlPageAndNavigationPaneOptions(rawValue: (tParams.value(forKey: "paneOptions") as! NSNumber).intValue)! // } self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: cachePath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["rtf", "RTF"]).contains(self.pathExtension) { autoreleasepool { self.pdfConverter = CPDFConverterRtf.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterRtf.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertRtfOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: self.desPath, pageIndexs: self.pages, options: self.options) } }else if !useOldLib && NSArray(array: ["txt", "TXT"]).contains(self.pathExtension) { autoreleasepool { self.pdfConverter = CPDFConverterTxt.init(url: url, password: nil) if (nil == self.pdfConverter && nil != password) { self.pdfConverter = CPDFConverterTxt.init(url: url, password: password as? String) } self.pdfConverter?.delegate = self self.options = CPDFConvertTxtOptions() self.configForOptions(self.options, inParams: tParams); self.pdfConverter?.convert(toFilePath: self.desPath, pageIndexs: self.pages, options: self.options) } }else { autoreleasepool { if self.fpConverter == nil { self.fpConverter = CPDFConverterFP.init() self.fpConverter?.setDelegate(self) }else { self.fpConverter?.stopConvertsionIfNeed() } var needMerge = NSArray(array: ["csv", "CSV"]).contains(self.pathExtension) let dpi = tParams.value(forKey: "KMPDFConvertOptionsKeyImageDPI") if (needMerge && tParams.value(forKey: "CPDFConvertOptionsKeyAllInOneSheet") != nil) { needMerge = (tParams.value(forKey: "CPDFConvertOptionsKeyAllInOneSheet") as! NSNumber).boolValue } self.fpConverter?.convertPDF(atPath: self.srcPath, pdfPassword: password as? String, pdfPageIndexs: self.pages, destDocType: self.pathExtension, destDocPath: self.desPath, moreOptions: [ "KMPDFConvertOptionsKeyImageDPI" : (dpi as? String) ?? "72", "CPDFConvertOptionsKeyAllInOneSheet":NSNumber(booleanLiteral: needMerge) ]) } } } } func converter(_ inSrcPath: String, inDesPath: String) -> Int { return converter(inSrcPath, inDesPath: inDesPath, params: nil) } func converter(_ inSrcPath: String, inDesPath: String, params:NSDictionary?) -> Int { if !FileManager.default.fileExists(atPath: inSrcPath) { return -1 } accessSemaphore?.wait() converter(inSrcPath, inDesPath: inDesPath, params: params) { status in self.semaphore?.signal() }; semaphore?.wait() accessSemaphore?.signal() return didSuccess } /// CPDFConverterDelegate func converter(_ converter: CPDFConverter!, didStartConvert error: Error!) { didSuccess = 0; } func converter(_ converter: CPDFConverter!, didEndConvert error: Error!) { didSuccess = nil == error ? 1 : 0 Thread.sleep(forTimeInterval: 0.1) autoreleasepool { if NSArray(array: ["jpg", "JPG", "png", "PNG", "HTML", "html", "csv", "CSV"]).contains(self.pathExtension) { let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip" let zip = ZipArchive.init() zip.unzipOpenFile(cachePath) zip.unzipFile(to: self.desPath, overWrite: true) try? FileManager.default.removeItem(atPath: cachePath) } if self.pdfConverter?.isConverting == true { self.pdfConverter?.cancel() } self.pdfConverter?.delegate = nil self.pdfConverter = nil self.complention(didSuccess) } } func converter(_ converter: CPDFConverter!, pageIndex index: UInt, pageCount count: UInt) { } /// CPDFConverterFPDelegate func fppdfConverter(_ converter: Any!, didEndConversion error: Error!) { autoreleasepool { didSuccess = nil == error ? 1 : 0 self.fpConverter?.stopConvertsionIfNeed() self.fpConverter = nil; Thread.sleep(forTimeInterval: 0.3) self.complention(didSuccess) } } /// Cancel func cancelTask() { if (self.fpConverter != nil) { self.fpConverter!.stopConvertsionIfNeed() self.fpConverter = nil; Thread.sleep(forTimeInterval: 0.3) } if (self.pdfConverter != nil) { self.pdfConverter?.delegate = nil if self.pdfConverter?.isConverting == true { self.pdfConverter?.cancel() } self.pdfConverter = nil Thread.sleep(forTimeInterval: 0.3) self.complention(didSuccess) } } func cancelTaskForSrcPath(_ srcPath:String) { if (NSString(string: srcPath).isEqual(to: self.originSrcPath)) { cancelTask(); } } // Config Options Tools func configForOptions(_ inOptions:CPDFConvertOptions?, inParams:NSDictionary?) { // Fetch Options Info let params = NSArray(array: (inParams?.value(forKey: "Options") as? [NSDictionary] ?? [])) // options is not empty or nil for param in params { PerformSelectTool.performSelector(inOptions as Any, params: param as! [AnyHashable : Any]); } } }