KMConvertURLToPDF.m 7.7 KB

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