KMConvertURLToPDF.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //
  2. // KMConvertURLToPDF.m
  3. // PDF Reader
  4. //
  5. // Created by 丁林圭 on 2019/3/11.
  6. // Copyright © 2019年 Kdan Mobile. All rights reserved.
  7. //
  8. #import "KMConvertURLToPDF.h"
  9. #import <WebKit/WebKit.h>
  10. #import <Quartz/Quartz.h>
  11. @interface KMConvertURLToPDF () <WebFrameLoadDelegate,WebResourceLoadDelegate>{
  12. BOOL isProgressing;
  13. }
  14. @property (nonatomic,retain) NSString *savePath;
  15. @property (nonatomic,assign) NSInteger pageIndex;
  16. @property (nonatomic,retain) NSMutableArray * urls;
  17. @property (nonatomic,retain) NSMutableArray * failArray;
  18. @property (nonatomic,retain) NSMutableArray * successArray;
  19. @property (nonatomic,assign) CGSize pageSize;
  20. @property (nonatomic,assign) CGFloat gap;
  21. @property (nonatomic,retain) WebView *webView;
  22. @property (nonatomic,copy) void (^progress)(CGFloat value);
  23. @property (nonatomic,copy) void (^handler)(NSArray *successArray,NSArray *failArray);
  24. @end
  25. @implementation KMConvertURLToPDF
  26. -(void)dealloc {
  27. }
  28. + (KMConvertURLToPDF *)shareInstance
  29. {
  30. static KMConvertURLToPDF *sharedConvertUrlToPDF = nil;
  31. static dispatch_once_t predicate;
  32. dispatch_once(&predicate, ^{
  33. sharedConvertUrlToPDF = [[KMConvertURLToPDF alloc] init];
  34. });
  35. return sharedConvertUrlToPDF;
  36. }
  37. - (void)convertUrlToPDF:(NSArray <NSURL *>*)urls
  38. toPath:(NSString *)toPath
  39. pageSize:(CGSize)pageSize
  40. gap:(CGFloat)gap
  41. progress:(void (^)(CGFloat value))progress
  42. completionHandler:(void (^) (NSArray *successArray,NSArray *failArray))handler
  43. {
  44. self.urls = [NSMutableArray arrayWithArray:urls];
  45. self.failArray = [NSMutableArray array];
  46. self.successArray = [NSMutableArray array];
  47. self.savePath = toPath;
  48. self.progress = progress;
  49. self.pageSize = pageSize;
  50. self.gap = gap;
  51. self.handler = handler;
  52. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  53. self.pageIndex = 0;
  54. dispatch_async(dispatch_get_main_queue(), ^{
  55. [self convertFileAtPageIndex:self.pageIndex];
  56. });
  57. });
  58. }
  59. - (void)convertFileAtPageIndex:(NSInteger)pageIndex
  60. {
  61. if (pageIndex >= self.urls.count) {
  62. if (self.handler) {
  63. self.handler (self.successArray,self.failArray);
  64. self.handler = nil;
  65. }
  66. return;
  67. }
  68. NSURL *url = self.urls[pageIndex];
  69. if ([url.pathExtension.lowercaseString isEqualToString:@"pdf"]) {
  70. NSData *urlData = [NSData dataWithContentsOfURL:url];
  71. NSString *name = [NSString stringWithFormat:@"webpage%ld",self.pageIndex];
  72. NSString *savePath = [self.savePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf",self.fileName?:name]];
  73. if ([urlData writeToFile:savePath atomically:YES]) {
  74. [self.successArray addObject:savePath];
  75. if (self.pageIndex + 1 >= self.urls.count) {
  76. if (self.handler) {
  77. self.handler (self.successArray,self.failArray);
  78. self.handler= nil;
  79. }
  80. } else {
  81. [self convertFileAtPageIndex:++self.pageIndex];
  82. }
  83. } else {
  84. [self.failArray addObject:self.urls[self.pageIndex]];
  85. if (self.handler) {
  86. self.handler (self.successArray,self.failArray);
  87. self.handler= nil;
  88. }
  89. }
  90. } else {
  91. if (!self.webView) {
  92. _webView = [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)];
  93. WebPreferences *webPrefs = [[WebPreferences alloc] init];
  94. [webPrefs setShouldPrintBackgrounds:YES];
  95. [self.webView setPreferences:webPrefs];
  96. [self.webView setFrameLoadDelegate:self];
  97. [self.webView setResourceLoadDelegate:self];
  98. }
  99. [[self.webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url]];
  100. }
  101. if (pageIndex != 0 && self.progress) {
  102. self.progress((float)self.pageIndex/self.urls.count);
  103. }
  104. }
  105. - (void)convertWebViewFrame:(WebFrame *)frame
  106. {
  107. // if (isProgressing) {
  108. // return;
  109. // }
  110. // isProgressing = YES;
  111. NSString *name = [NSString stringWithFormat:@"webpage%ld",self.pageIndex];
  112. if (self.fileName.length != 0) {
  113. name = self.fileName;
  114. }
  115. NSString *savePath = [self.savePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf",name]];
  116. CGFloat margin = self.gap;
  117. NSSize paperSize = self.pageSize;
  118. WebFrameView *frameView = [frame frameView];
  119. NSPrintInfo *sharedInfo = [NSPrintInfo sharedPrintInfo];
  120. NSMutableDictionary *printInfoDict = [NSMutableDictionary dictionaryWithDictionary:[sharedInfo dictionary]];
  121. [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
  122. [printInfoDict setObject:[NSURL fileURLWithPath:savePath] forKey:NSPrintJobSavingURL];
  123. NSPrintInfo *printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];
  124. [printInfo setHorizontalPagination:NSPrintingPaginationModeAutomatic];
  125. [printInfo setVerticalPagination:NSPrintingPaginationModeAutomatic];
  126. [printInfo setVerticallyCentered:NO];
  127. if (!CGSizeEqualToSize(paperSize, CGSizeZero)) {
  128. [printInfo setBottomMargin:margin];
  129. [printInfo setTopMargin:margin];
  130. [printInfo setLeftMargin:margin];
  131. [printInfo setRightMargin:margin];
  132. [printInfo setPaperSize:paperSize];
  133. }
  134. [printInfo setOrientation:NSPaperOrientationPortrait];
  135. NSPrintOperation *printOp = [frameView printOperationWithPrintInfo:printInfo];
  136. [printOp setShowsPrintPanel:NO];
  137. [printOp setShowsProgressPanel:NO];
  138. if ([printOp runOperation]) {
  139. [self.successArray addObject:savePath];
  140. if (self.pageIndex + 1 >= self.urls.count) {
  141. if (self.handler) {
  142. self.handler (self.successArray,self.failArray);
  143. self.handler= nil;
  144. }
  145. } else {
  146. [self convertFileAtPageIndex:++self.pageIndex];
  147. }
  148. } else {
  149. [self.failArray addObject:self.urls[self.pageIndex]];
  150. if (self.handler) {
  151. self.handler (self.successArray,self.failArray);
  152. self.handler= nil;
  153. }
  154. }
  155. }
  156. #pragma mark - WebView Delegate Methods
  157. - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
  158. if (frame == [sender mainFrame]) {
  159. NSString *htmlTitle = @"document.title";
  160. if (!self.fileName) {
  161. self.fileName = [sender stringByEvaluatingJavaScriptFromString:htmlTitle];
  162. if ([self.fileName length] < 1) {
  163. self.fileName = sender.mainFrameTitle;
  164. }
  165. if ([self.fileName length] < 1) {
  166. self.fileName = @"Untitled";
  167. }
  168. }
  169. [self performSelector:@selector(convertWebViewFrame:) withObject:frame afterDelay:0.3];
  170. }
  171. }
  172. - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
  173. {
  174. if([error code] == NSURLErrorCancelled) {
  175. return;
  176. }
  177. [self.failArray addObject:self.urls[self.pageIndex]];
  178. if (self.handler) {
  179. self.handler (self.successArray,self.failArray);
  180. self.handler= nil;
  181. }
  182. }
  183. - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
  184. {
  185. [self.failArray addObject:self.urls[self.pageIndex]];
  186. if (self.handler) {
  187. self.handler (self.successArray,self.failArray);
  188. self.handler= nil;
  189. }
  190. }
  191. @end