KMConvertURLToPDF.m 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. dispatch_async(dispatch_get_main_queue(), ^{
  71. NSData *urlData = [NSData dataWithContentsOfURL:url];
  72. NSString *name = [NSString stringWithFormat:@"webpage%ld",self.pageIndex];
  73. NSString *savePath = [self.savePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", self.fileName.length > 0? self.fileName : name]];
  74. if (![[NSFileManager defaultManager]fileExistsAtPath:self.savePath]) {
  75. [[NSFileManager defaultManager] createDirectoryAtPath:self.savePath withIntermediateDirectories:YES attributes:nil error:nil];
  76. }
  77. if ([urlData writeToFile:savePath atomically:YES]) {
  78. [self.successArray addObject:savePath];
  79. if (self.pageIndex + 1 >= self.urls.count) {
  80. if (self.handler) {
  81. self.handler (self.successArray,self.failArray);
  82. self.handler= nil;
  83. }
  84. } else {
  85. [self convertFileAtPageIndex:++self.pageIndex];
  86. }
  87. } else {
  88. [self.failArray addObject:self.urls[self.pageIndex]];
  89. if (self.handler) {
  90. self.handler (self.successArray,self.failArray);
  91. self.handler= nil;
  92. }
  93. }
  94. });
  95. } else {
  96. if (!self.webView) {
  97. _webView = [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)];
  98. WebPreferences *webPrefs = [[WebPreferences alloc] init];
  99. [webPrefs setShouldPrintBackgrounds:YES];
  100. [self.webView setPreferences:webPrefs];
  101. [self.webView setFrameLoadDelegate:self];
  102. [self.webView setResourceLoadDelegate:self];
  103. }
  104. [[self.webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url]];
  105. }
  106. if (pageIndex != 0 && self.progress) {
  107. self.progress((float)self.pageIndex/self.urls.count);
  108. }
  109. }
  110. - (void)convertWebViewFrame:(WebFrame *)frame
  111. {
  112. // if (isProgressing) {
  113. // return;
  114. // }
  115. // isProgressing = YES;
  116. NSString *name = [NSString stringWithFormat:@"webpage%ld",self.pageIndex];
  117. if (self.fileName.length != 0) {
  118. name = self.fileName;
  119. }
  120. NSString *savePath = [self.savePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf",name]];
  121. if (![[NSFileManager defaultManager]fileExistsAtPath:self.savePath]) {
  122. [[NSFileManager defaultManager] createDirectoryAtPath:self.savePath withIntermediateDirectories:YES attributes:nil error:nil];
  123. }
  124. CGFloat margin = self.gap;
  125. NSSize paperSize = self.pageSize;
  126. WebFrameView *frameView = [frame frameView];
  127. NSPrintInfo *sharedInfo = [NSPrintInfo sharedPrintInfo];
  128. NSMutableDictionary *printInfoDict = [NSMutableDictionary dictionaryWithDictionary:[sharedInfo dictionary]];
  129. [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
  130. [printInfoDict setObject:[NSURL fileURLWithPath:savePath] forKey:NSPrintJobSavingURL];
  131. NSPrintInfo *printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];
  132. [printInfo setHorizontalPagination:NSPrintingPaginationModeAutomatic];
  133. [printInfo setVerticalPagination:NSPrintingPaginationModeAutomatic];
  134. [printInfo setVerticallyCentered:NO];
  135. if (!CGSizeEqualToSize(paperSize, CGSizeZero)) {
  136. [printInfo setBottomMargin:margin];
  137. [printInfo setTopMargin:margin];
  138. [printInfo setLeftMargin:margin];
  139. [printInfo setRightMargin:margin];
  140. [printInfo setPaperSize:paperSize];
  141. }
  142. [printInfo setOrientation:NSPaperOrientationPortrait];
  143. NSPrintOperation *printOp = [frameView printOperationWithPrintInfo:printInfo];
  144. [printOp setShowsPrintPanel:NO];
  145. [printOp setShowsProgressPanel:NO];
  146. if ([printOp runOperation]) {
  147. [self.successArray addObject:savePath];
  148. if (self.pageIndex + 1 >= self.urls.count) {
  149. if (self.handler) {
  150. self.handler (self.successArray,self.failArray);
  151. self.handler= nil;
  152. }
  153. } else {
  154. [self convertFileAtPageIndex:++self.pageIndex];
  155. }
  156. } else {
  157. [self.failArray addObject:self.urls[self.pageIndex]];
  158. if (self.handler) {
  159. self.handler (self.successArray,self.failArray);
  160. self.handler= nil;
  161. }
  162. }
  163. }
  164. #pragma mark - WebView Delegate Methods
  165. - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
  166. if (frame == [sender mainFrame]) {
  167. NSString *htmlTitle = @"document.title";
  168. if (!self.fileName) {
  169. self.fileName = [sender stringByEvaluatingJavaScriptFromString:htmlTitle];
  170. if ([self.fileName length] < 1) {
  171. self.fileName = sender.mainFrameTitle;
  172. }
  173. if ([self.fileName length] < 1) {
  174. self.fileName = @"Untitled";
  175. }
  176. }
  177. [self performSelector:@selector(convertWebViewFrame:) withObject:frame afterDelay:0.3];
  178. }
  179. }
  180. - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
  181. {
  182. if([error code] == NSURLErrorCancelled) {
  183. return;
  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. - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
  192. {
  193. [self.failArray addObject:self.urls[self.pageIndex]];
  194. if (self.handler) {
  195. self.handler (self.successArray,self.failArray);
  196. self.handler= nil;
  197. }
  198. }
  199. @end