FileConverter.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. //
  2. // FileConverter.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2022/12/21.
  6. //
  7. import Foundation
  8. import ComPDFKit_Conversion
  9. import PDFKit
  10. let KMComPDFKit_Conversion_FreeKey = "hw5vIMzKU2Im6cPijLjG45VAHy01ikUF5/GdAMdzCV8n2QTKNN0d8kG8crVbGYjIMsvVP+A9gx5g+W8qEi4ho0YTkGDratHOrX68W7khEBHAv7OEyRxIhlhBmdEQD+21lsRpIEW5zucUAF231lo3ZZiiT2s9CualDQJdAo1G0DI=";
  11. let KMComPDFKit_Conversion_FreeSecret = "mG0c3O3Mzeu5dkZJW3gpqh188cTuhYlGRPrbR/gfX4p9ms/F1zY6gZ1RBu8mNJH8zLwqe9EJswNmwV09TNi2IiIDeG7Ulx+U4pbeFB3/eYl2J6LePb3Kl54OsKlYiaf3Mv7C2jvq4o0q6sQtN3jR4897KG6mIUGJSRuOsvjYroVgMwna6EUx0K0SBmBGoFYDYkwcNWVMyYvggPV2rTFvfawopGIC034QzjthmhwwX90=";
  12. let KMPDFConvertOptionsKeyImageDPI = "KMPDFConvertOptionsKeyImageDPI"
  13. let KMPDFConvertOptionsKeyImageWithAnnotation = "KMPDFConvertOptionsKeyImageWithAnnotation"
  14. let kDefaultPassword = "666666"
  15. class FileConverter : NSObject, CPDFConverterDelegate, CPDFConverterFPDelegate {
  16. var pdfConverter:CPDFConverter?
  17. var fpConverter:CPDFConverterFP?
  18. var options:CPDFConvertOptions?
  19. var originSrcPath:String = ""
  20. var srcPath:String = ""
  21. var desPath:String = ""
  22. var pages:[Int] = []
  23. var pathExtension = ""
  24. var convertQueue = DispatchQueue.main
  25. var semaphore:DispatchSemaphore? = DispatchSemaphore.init(value: 0)
  26. var accessSemaphore:DispatchSemaphore? = DispatchSemaphore.init(value: 1)
  27. var didSuccess:Int = 1
  28. let m_currentVersion = CPDFConvertKit.sharedInstance().buildNumber
  29. var complention = { (status:Int) in
  30. }
  31. static var instance = FileConverter()
  32. class func shared() -> FileConverter {
  33. return instance
  34. }
  35. func converter(_ inSrcPath: String, inDesPath: String, complention:@escaping (_ status:Int) -> ()) {
  36. return converter(inSrcPath, inDesPath: inDesPath, params: nil, complention: complention)
  37. }
  38. func converter(_ inSrcPath: String, inDesPath: String, params:NSDictionary?, complention:@escaping (_ status:Int) -> ()) {
  39. self.complention = complention;
  40. if !FileManager.default.fileExists(atPath: inSrcPath) {
  41. self.complention(-1)
  42. return
  43. }
  44. self.originSrcPath = inSrcPath;
  45. self.srcPath = inSrcPath
  46. self.desPath = inDesPath
  47. if FileManager.default.fileExists(atPath: desPath) {
  48. try? FileManager.default.removeItem(atPath: desPath)
  49. }
  50. let directory = NSString(string: desPath).deletingLastPathComponent
  51. if !FileManager.default.fileExists(atPath: directory) {
  52. try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true)
  53. }
  54. let attributy = try! FileManager.default.attributesOfItem(atPath: srcPath)
  55. let fileType = attributy[FileAttributeKey.type] as! FileAttributeType
  56. if NSString(string: FileAttributeType.typeSymbolicLink.rawValue).isEqual(to: fileType.rawValue) {
  57. let symbolicLink = try? FileManager.default.destinationOfSymbolicLink(atPath: self.srcPath)
  58. if nil != symbolicLink {
  59. self.srcPath = symbolicLink!
  60. }
  61. }
  62. if FileManager.default.fileExists(atPath: self.desPath) {
  63. try? FileManager.default.removeItem(atPath: self.desPath)
  64. }
  65. self.pathExtension = NSString(string: self.desPath).pathExtension
  66. // let outputPath = NSString(string: self.desPath).deletingPathExtension
  67. // let output = self.desPath
  68. let password = params?.value(forKey: "password")
  69. let tParams = params ?? [:]
  70. let useOldLibValue = params?.value(forKey: "useOldLib")
  71. var useOldLib = false;
  72. if (nil != useOldLibValue) {
  73. if ((useOldLibValue as? String) != nil) {
  74. useOldLib = NSArray(array: ["TRUE", "true", "1"]).contains((useOldLibValue as! String))
  75. }else if ((useOldLibValue as? NSNumber) != nil) {
  76. useOldLib = (useOldLibValue as? NSNumber)!.boolValue || (useOldLibValue as? NSNumber)!.intValue == 1
  77. }
  78. }
  79. // NSLog("%@ - %@\n\(inSrcPath)", useOldLib ? "老库" : "新库", params ?? "")
  80. self.convertQueue.async {
  81. if (LogViewController.shared().isVisable()) {
  82. LogViewController.shared().appendLog("\n转档:\(NSString(string: inSrcPath).lastPathComponent)\n")
  83. }
  84. let url = URL.init(fileURLWithPath: self.srcPath, isDirectory: false)
  85. let document = PDFDocument(url: url)
  86. if document == nil {
  87. self.didSuccess = -2;
  88. self.accessSemaphore?.signal()
  89. return
  90. }
  91. let pageCount = document!.pageCount
  92. self.pages = []
  93. for i in 1...pageCount {
  94. self.pages.append(i)
  95. }
  96. if !useOldLib && NSArray(array: ["jpg", "JPG", "png", "PNG"]).contains(self.pathExtension) {
  97. autoreleasepool {
  98. let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip"
  99. self.pdfConverter = CPDFConverterImg.init(url: url, password: nil)
  100. if (nil == self.pdfConverter && nil != password) {
  101. self.pdfConverter = CPDFConverterImg.init(url: url, password: password as? String)
  102. }
  103. self.pdfConverter?.delegate = self
  104. self.options = CPDFConvertImgOptions()
  105. var fileType = "JPG"
  106. if (NSArray(array: ["jpg", "JPG"]).contains(self.pathExtension)) {
  107. (self.options as! CPDFConvertImgOptions).type = .JPEG
  108. }else {
  109. (self.options as! CPDFConvertImgOptions).type = .PNG
  110. fileType = "PNG"
  111. }
  112. self.configForOptions(self.options, inParams: tParams);
  113. self.showLog(self.options, fileType: fileType)
  114. do {
  115. try? self.pdfConverter?.convert(toFilePath: cachePath, pageIndexs: self.pages, options: self.options)
  116. }catch {
  117. self.didSuccess = -1;
  118. self.complention(self.didSuccess)
  119. }
  120. }
  121. }else if !useOldLib && NSArray(array: ["ppt", "PPT", "PPTX", "pptx"]).contains(self.pathExtension) {
  122. autoreleasepool {
  123. self.pdfConverter = CPDFConverterPPT.init(url: url, password: nil)
  124. if (nil == self.pdfConverter && nil != password) {
  125. self.pdfConverter = CPDFConverterPPT.init(url: url, password: password as? String)
  126. }
  127. self.pdfConverter?.delegate = self
  128. self.options = CPDFConvertPPTOptions()
  129. self.configForOptions(self.options, inParams: tParams);
  130. self.showLog(self.options, fileType: "PPT")
  131. self.pdfConverter?.convert(toFilePath: self.desPath,
  132. pageIndexs: self.pages, options: self.options)
  133. }
  134. }else if !useOldLib && NSArray(array: ["doc", "DOC", "docx", "DOCX"]).contains(self.pathExtension) {
  135. autoreleasepool {
  136. self.pdfConverter = CPDFConverterWord.init(url: url, password: nil)
  137. if (nil == self.pdfConverter && nil != password) {
  138. self.pdfConverter = CPDFConverterWord.init(url: url, password: password as? String)
  139. }
  140. self.pdfConverter?.delegate = self
  141. self.options = CPDFConvertWordOptions()
  142. self.configForOptions(self.options, inParams: tParams);
  143. self.showLog(self.options, fileType: "Word")
  144. self.pdfConverter?.convert(toFilePath: self.desPath,
  145. pageIndexs: self.pages, options: self.options)
  146. }
  147. }else if !useOldLib && NSArray(array: ["xls", "XLS", "xlsx", "XLSX"]).contains(self.pathExtension) {
  148. autoreleasepool {
  149. self.pdfConverter = CPDFConverterExcel.init(url: url, password: nil)
  150. if (nil == self.pdfConverter && nil != password) {
  151. self.pdfConverter = CPDFConverterExcel.init(url: url, password: password as? String)
  152. }
  153. self.pdfConverter?.delegate = self
  154. self.options = CPDFConvertExcelOptions()
  155. self.configForOptions(self.options, inParams: tParams);
  156. self.showLog(self.options, fileType: "Excel")
  157. self.pdfConverter?.convert(toFilePath: self.desPath,
  158. pageIndexs: self.pages, options: self.options)
  159. }
  160. }else if !useOldLib && NSArray(array: ["csv", "CSV"]).contains(self.pathExtension) {
  161. autoreleasepool {
  162. let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip"
  163. self.pdfConverter = CPDFConverterCsv.init(url: url, password: nil)
  164. if (nil == self.pdfConverter && nil != password) {
  165. self.pdfConverter = CPDFConverterCsv.init(url: url, password: password as? String)
  166. }
  167. self.pdfConverter?.delegate = self
  168. self.options = CPDFConvertCsvOptions()
  169. self.configForOptions(self.options, inParams: tParams);
  170. self.showLog(self.options, fileType: "CSV")
  171. self.pdfConverter?.convert(toFilePath: cachePath,
  172. pageIndexs: self.pages, options: self.options)
  173. }
  174. }else if !useOldLib && NSArray(array: ["html", "HTML"]).contains(self.pathExtension) {
  175. autoreleasepool {
  176. let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip"
  177. self.pdfConverter = CPDFConverterHtml.init(url: url, password: nil)
  178. if (nil == self.pdfConverter && nil != password) {
  179. self.pdfConverter = CPDFConverterHtml.init(url: url, password: password as? String)
  180. }
  181. self.pdfConverter?.delegate = self
  182. self.options = CPDFConvertHtmlOptions()
  183. self.configForOptions(self.options, inParams: tParams);
  184. self.showLog(self.options, fileType: "HTML")
  185. self.pdfConverter?.convert(toFilePath: cachePath,
  186. pageIndexs: self.pages, options: self.options)
  187. }
  188. }else if !useOldLib && NSArray(array: ["rtf", "RTF"]).contains(self.pathExtension) {
  189. autoreleasepool {
  190. self.pdfConverter = CPDFConverterRtf.init(url: url, password: nil)
  191. if (nil == self.pdfConverter && nil != password) {
  192. self.pdfConverter = CPDFConverterRtf.init(url: url, password: password as? String)
  193. }
  194. self.pdfConverter?.delegate = self
  195. self.options = CPDFConvertRtfOptions()
  196. self.configForOptions(self.options, inParams: tParams);
  197. self.showLog(self.options, fileType: "RTF")
  198. self.pdfConverter?.convert(toFilePath: self.desPath,
  199. pageIndexs: self.pages, options: self.options)
  200. }
  201. }else if !useOldLib && NSArray(array: ["txt", "TXT"]).contains(self.pathExtension) {
  202. autoreleasepool {
  203. self.pdfConverter = CPDFConverterTxt.init(url: url, password: nil)
  204. if (nil == self.pdfConverter && nil != password) {
  205. self.pdfConverter = CPDFConverterTxt.init(url: url, password: password as? String)
  206. }
  207. self.pdfConverter?.delegate = self
  208. self.options = CPDFConvertTxtOptions()
  209. self.configForOptions(self.options, inParams: tParams);
  210. self.showLog(self.options, fileType: "TXT")
  211. self.pdfConverter?.convert(toFilePath: self.desPath,
  212. pageIndexs: self.pages, options: self.options)
  213. }
  214. }else {
  215. autoreleasepool {
  216. if self.fpConverter == nil {
  217. self.fpConverter = CPDFConverterFP.init()
  218. self.fpConverter?.setDelegate(self)
  219. }else {
  220. self.fpConverter?.stopConvertsionIfNeed()
  221. }
  222. var needMerge = NSArray(array: ["csv", "CSV"]).contains(self.pathExtension)
  223. let dpi = tParams.value(forKey: "KMPDFConvertOptionsKeyImageDPI")
  224. if (needMerge && tParams.value(forKey: "CPDFConvertOptionsKeyAllInOneSheet") != nil) {
  225. needMerge = (tParams.value(forKey: "CPDFConvertOptionsKeyAllInOneSheet") as! NSNumber).boolValue
  226. }
  227. if (LogViewController.shared().isVisable()) {
  228. LogViewController.shared().appendLog("转档参数\n")
  229. LogViewController.shared().appendLog("- 库版本: 老库\n")
  230. let options = [
  231. "KMPDFConvertOptionsKeyImageDPI" : (dpi as? String) ?? "72",
  232. "CPDFConvertOptionsKeyAllInOneSheet":NSNumber(booleanLiteral: needMerge)
  233. ]
  234. LogViewController.shared().appendLog("- 其它参数:\(options)\n")
  235. }
  236. self.fpConverter?.convertPDF(atPath: self.srcPath,
  237. pdfPassword: password as? String,
  238. pdfPageIndexs: self.pages,
  239. destDocType: self.pathExtension,
  240. destDocPath: self.desPath,
  241. moreOptions: [
  242. "KMPDFConvertOptionsKeyImageDPI" : (dpi as? String) ?? "72",
  243. "CPDFConvertOptionsKeyAllInOneSheet":NSNumber(booleanLiteral: needMerge)
  244. ])
  245. }
  246. }
  247. }
  248. }
  249. func converter(_ inSrcPath: String, inDesPath: String) -> Int {
  250. return converter(inSrcPath, inDesPath: inDesPath, params: nil)
  251. }
  252. func converter(_ inSrcPath: String, inDesPath: String, params:NSDictionary?) -> Int {
  253. if !FileManager.default.fileExists(atPath: inSrcPath) {
  254. return -1
  255. }
  256. accessSemaphore?.wait()
  257. converter(inSrcPath, inDesPath: inDesPath, params: params) { status in
  258. self.semaphore?.signal()
  259. };
  260. semaphore?.wait()
  261. accessSemaphore?.signal()
  262. return didSuccess
  263. }
  264. /// CPDFConverterDelegate
  265. func converter(_ converter: CPDFConverter!, didStartConvert error: Error!) {
  266. didSuccess = 0;
  267. }
  268. func converter(_ converter: CPDFConverter!, didEndConvert error: Error!) {
  269. didSuccess = nil == error ? 1 : 0
  270. Thread.sleep(forTimeInterval: 0.1)
  271. autoreleasepool {
  272. if NSArray(array: ["jpg", "JPG", "png", "PNG", "HTML", "html", "csv", "CSV"]).contains(self.pathExtension) {
  273. let cachePath = NSString(string: self.desPath).deletingPathExtension+".zip"
  274. let zip = ZipArchive.init()
  275. zip.unzipOpenFile(cachePath)
  276. zip.unzipFile(to: self.desPath, overWrite: true)
  277. try? FileManager.default.removeItem(atPath: cachePath)
  278. }
  279. if self.pdfConverter?.isConverting == true {
  280. self.pdfConverter?.cancel()
  281. }
  282. self.pdfConverter?.delegate = nil
  283. self.pdfConverter = nil
  284. self.complention(didSuccess)
  285. }
  286. }
  287. func converter(_ converter: CPDFConverter!, pageIndex index: UInt, pageCount count: UInt) {
  288. }
  289. /// CPDFConverterFPDelegate
  290. func fppdfConverter(_ converter: Any!, didEndConversion error: Error!) {
  291. autoreleasepool {
  292. didSuccess = nil == error ? 1 : 0
  293. self.fpConverter?.stopConvertsionIfNeed()
  294. self.fpConverter = nil;
  295. Thread.sleep(forTimeInterval: 0.3)
  296. self.complention(didSuccess)
  297. }
  298. }
  299. /// Cancel
  300. func cancelTask() {
  301. if (self.fpConverter != nil) {
  302. self.fpConverter!.stopConvertsionIfNeed()
  303. self.fpConverter = nil;
  304. Thread.sleep(forTimeInterval: 0.3)
  305. }
  306. if (self.pdfConverter != nil) {
  307. self.pdfConverter?.delegate = nil
  308. if self.pdfConverter?.isConverting == true {
  309. self.pdfConverter?.cancel()
  310. }
  311. self.pdfConverter = nil
  312. Thread.sleep(forTimeInterval: 0.3)
  313. self.complention(didSuccess)
  314. }
  315. }
  316. func cancelTaskForSrcPath(_ srcPath:String) {
  317. if (NSString(string: srcPath).isEqual(to: self.originSrcPath)) {
  318. cancelTask();
  319. }
  320. }
  321. // Config Options Tools
  322. func configForOptions(_ inOptions:CPDFConvertOptions?, inParams:NSDictionary?) {
  323. // Fetch Options Info
  324. let params = NSArray(array: (inParams?.value(forKey: "Options") as? [NSDictionary] ?? []))
  325. // options is not empty or nil
  326. for param in params {
  327. PerformSelectTool.performSelector(inOptions as Any, params: param as! [AnyHashable : Any]);
  328. }
  329. }
  330. // Show Options
  331. func showLog(_ options:CPDFConvertOptions?, fileType:String) {
  332. if (LogViewController.shared().isVisable()) {
  333. LogViewController.shared().appendLog("[\(fileType)]转档参数\n")
  334. LogViewController.shared().appendLog("- 库版本: 新库\n")
  335. let info = AdvanceSettingViewController.baseInfoFor(fileType)
  336. let paramStrings = PerformSelectTool.paramsLog(with: options!, paramRules: info as! [AnyHashable : Any])
  337. for string in paramStrings {
  338. LogViewController.shared().appendLog("- \(string as! String)\n")
  339. }
  340. }
  341. }
  342. }