webentwicklung-frage-antwort-db.com.de

Erstellen PDF Datei von UIWebView

 -(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
  UIWebView *webView = (UIWebView*)aView;
    NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];

    int height = [heightStr intValue];

    // Get the number of pages needed to print. 9 * 72 = 648
    int pages = ceil(height / 648.0);

    NSMutableData *pdfData = [NSMutableData data];
    UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
  CGRect frame = [webView frame];
    for (int i = 0; i < pages; i++) {
      // Check to see if page draws more than the height of the UIWebView
        if ((i+1) * 648 > height) {
            CGRect f = [webView frame];
            f.size.height -= (((i+1) * 648.0) - height);
            [webView setFrame: f];
        }

        UIGraphicsBeginPDFPage();
        CGContextRef currentContext = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(currentContext, 72, 72); // Translate for 1" margins

        [[[webView subviews] lastObject] setContentOffset:CGPointMake(0, 648 * i) animated:NO];
        [webView.layer renderInContext:currentContext];
    }

    UIGraphicsEndPDFContext();
    // Retrieves the document directories from the iOS device
  NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

  NSString* documentDirectory = [documentDirectories objectAtIndex:0];
  NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
  [pdfData writeToFile:documentDirectoryFilename atomically:YES];
  [webView setFrame:frame];
  NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}

Ich benutze den obigen Code, um eine PDF-Datei aus einer Webansicht zu generieren. Es funktioniert jedoch, der Inhalt wird nicht korrekt zugeschnitten: Der Inhalt am unteren Rand der Seiten ist durcheinander. Ich denke, ich könnte mit Core Graphics-Methoden etwas besseres machen, aber ich kann nicht herausfinden, wie das geht. Irgendwelche Ideen ?

18
AnderCover

Verwenden Sie UIPrintPageRenderer aus UIWebView Befolgen Sie die folgenden Schritte:

Fügen Sie Category von UIPrintPageRenderer hinzu, um PDF Daten abzurufen

@interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
@end

@implementation UIPrintPageRenderer (PDF)
- (NSData*) printToPDF
{
  NSMutableData *pdfData = [NSMutableData data];
  UIGraphicsBeginPDFContextToData( pdfData, self.paperRect, nil );
  [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];
  CGRect bounds = UIGraphicsGetPDFContextBounds();
  for ( int i = 0 ; i < self.numberOfPages ; i++ )
  {
    UIGraphicsBeginPDFPage();
    [self drawPageAtIndex: i inRect: bounds];
  }
  UIGraphicsEndPDFContext();
  return pdfData;
}
@end

Fügen Sie diese für das A4-Format hinzu

#define kPaperSizeA4 CGSizeMake(595.2,841.8)

Verwenden Sie jetzt in UIWebView'swebViewDidFinishLoaddelegateUIPrintPageRendererproperty von UIWebView.

- (void)webViewDidFinishLoad:(UIWebView *)awebView
{
  if (awebView.isLoading)
    return;

  UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
  [render addPrintFormatter:awebView.viewPrintFormatter startingAtPageAtIndex:0];
  //increase these values according to your requirement
  float topPadding = 10.0f;
  float bottomPadding = 10.0f;
  float leftPadding = 10.0f;
  float rightPadding = 10.0f;
  CGRect printableRect = CGRectMake(leftPadding,
                                  topPadding,
                                  kPaperSizeA4.width-leftPadding-rightPadding,
                                  kPaperSizeA4.height-topPadding-bottomPadding);
  CGRect paperRect = CGRectMake(0, 0, kPaperSizeA4.width, kPaperSizeA4.height);
  [render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"];
  [render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"];
  NSData *pdfData = [render printToPDF];
  if (pdfData) {
    [pdfData writeToFile:[NSString stringWithFormat:@"%@/tmp.pdf",NSTemporaryDirectory()] atomically: YES];
  }
  else
  {
    NSLog(@"PDF couldnot be created");
  }
}
15
Paresh Navadiya

Vielen Dank für Ihre Antworten Firemarble, es hat mir sehr geholfen. Ich habe es geschafft, mit dieser Methode ein etwas gut aussehendes Ergebnis zu erzielen:

-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
  UIWebView *webView = (UIWebView*)aView;
    NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];

    int height = [heightStr intValue];
//  CGRect screenRect = [[UIScreen mainScreen] bounds];
//  CGFloat screenHeight = (self.contentWebView.hidden)?screenRect.size.width:screenRect.size.height;
  CGFloat screenHeight = webView.bounds.size.height;
    int pages = ceil(height / screenHeight);

  NSMutableData *pdfData = [NSMutableData data];
  UIGraphicsBeginPDFContextToData(pdfData, webView.bounds, nil);
 CGRect frame = [webView frame];
    for (int i = 0; i < pages; i++) {
      // Check to screenHeight if page draws more than the height of the UIWebView
        if ((i+1) * screenHeight  > height) {
            CGRect f = [webView frame];
            f.size.height -= (((i+1) * screenHeight) - height);
            [webView setFrame: f];
        }

        UIGraphicsBeginPDFPage();
        CGContextRef currentContext = UIGraphicsGetCurrentContext();
//      CGContextTranslateCTM(currentContext, 72, 72); // Translate for 1" margins

        [[[webView subviews] lastObject] setContentOffset:CGPointMake(0, screenHeight * i) animated:NO];
        [webView.layer renderInContext:currentContext];
    }

    UIGraphicsEndPDFContext();
    // Retrieves the document directories from the iOS device
  NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

  NSString* documentDirectory = [documentDirectories objectAtIndex:0];
  NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
  [pdfData writeToFile:documentDirectoryFilename atomically:YES];
  [webView setFrame:frame];
}
11
AnderCover

Swift 2.0-Lösung zum Speichern von PDF-Dateien aus Webview in NSData:

func webViewDidFinishLoad(webView: UIWebView) {
    let pdfData = createPdfFile(webView.viewPrintFormatter())
    pdfData.writeToFile("/path/to/file", atomically: true)
}

func createPdfFile(printFormatter: UIViewPrintFormatter) -> NSData {
    let renderer = UIPrintPageRenderer()
    renderer.addPrintFormatter(printFormatter, startingAtPageAtIndex: 0);
    let paperSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height)
    let printableRect = CGRectMake(0, 0, paperSize.width, paperSize.height)
    let paperRect = CGRectMake(0, 0, paperSize.width, paperSize.height);
    renderer.setValue(NSValue(CGRect: paperRect), forKey: "paperRect")
    renderer.setValue(NSValue(CGRect: printableRect), forKey: "printableRect")
    return renderer.printToPDF()
}

Sie müssen auch UIWebViewDelegate zu Ihrem ViewController und der Erweiterung für UIPrintPageRenderer hinzufügen.

extension UIPrintPageRenderer {
    func printToPDF() -> NSData {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
        self.prepareForDrawingPages(NSMakeRange(0, self.numberOfPages()))
        let bounds = UIGraphicsGetPDFContextBounds()
        for i in 0..<self.numberOfPages() {
            UIGraphicsBeginPDFPage();
            self.drawPageAtIndex(i, inRect: bounds)
        }
        UIGraphicsEndPDFContext();
        return pdfData;
    }
}
9
Konrad Siemczyk

Swift 3 Lösung von @Dan Loewenherz Antwort:

func webViewDidFinishLoad(_ webView: UIWebView) {
    let pdfData = createPdfFile(printFormatter: webView.viewPrintFormatter())
    pdfData.write(toFile: "/path/to/file", atomically: true)
}

func createPdfFile(printFormatter: UIViewPrintFormatter) -> NSData {
    let renderer = UIPrintPageRenderer()
    renderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
    let point = CGPoint(x:0,y:0)
    let paperSize = CGSize(width: self.view.frame.size.width, height: self.view.frame.size.height)
    let printableRect = CGRect(Origin: point, size: CGSize(width:paperSize.width, height: paperSize.height))
    let paperRect = CGRect(Origin: point, size: CGSize(width: paperSize.width, height: paperSize.height))
    renderer.setValue(NSValue(cgRect: paperRect), forKey: "paperRect")
    renderer.setValue(NSValue(cgRect: printableRect), forKey: "printableRect")
    return renderer.printToPDF()
}

extension UIPrintPageRenderer {
    func printToPDF() -> NSData {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
        self.prepare(forDrawingPages: NSMakeRange(0, self.numberOfPages))
        let bounds = UIGraphicsGetPDFContextBounds()
        for i in 0..<self.numberOfPages {
            UIGraphicsBeginPDFPage();
            self.drawPage(at: i, in: bounds)
        }
        UIGraphicsEndPDFContext();
        return pdfData;
    }
}
6
Alfi

Es sieht so aus, als ob das Problem von der fest codierten Höhe 648 herrühren könnte. Was passiert, wenn Sie alle Instanzen von 648 so ändern, dass Windows screenHeight aufgerufen wird?

// Ergreife die Breite und Höhe der Fenster.

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
1
user-44651

UIWebView ist jetzt veraltet. Verwenden Sie die WKWebView-Erweiterung, um PDF aus WKWebView zu erstellen

Gutschrift: http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/

Swift 4.2

extension WKWebView {

    // Call this function when WKWebView finish loading
    func exportAsPdfFromWebView() -> String {
        let pdfData = createPdfFile(printFormatter: self.viewPrintFormatter())
        return self.saveWebViewPdf(data: pdfData)
    }

    func createPdfFile(printFormatter: UIViewPrintFormatter) -> NSMutableData {
        let originalBounds = self.bounds
        self.bounds = CGRect(x: originalBounds.Origin.x,
                             y: bounds.Origin.y,
                             width: self.bounds.size.width,
                             height: self.scrollView.contentSize.height)
        let pdfPageFrame = CGRect(x: 0, y: 0, width: self.bounds.size.width,
                                  height: self.scrollView.contentSize.height)
        let printPageRenderer = UIPrintPageRenderer()
        printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
        printPageRenderer.setValue(NSValue(cgRect: UIScreen.main.bounds), forKey: "paperRect")
        printPageRenderer.setValue(NSValue(cgRect: pdfPageFrame), forKey: "printableRect")
        self.bounds = originalBounds
        return printPageRenderer.generatePdfData()
    }

    // Save pdf file in document directory
    func saveWebViewPdf(data: NSMutableData) -> String {

        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let docDirectoryPath = paths[0]
        let pdfPath = docDirectoryPath.appendingPathComponent("webViewPdf.pdf")
        if data.write(to: pdfPath, atomically: true) {
            return pdfPath.path
        } else {
            return ""
        }
    }
}
extension UIPrintPageRenderer {

    func generatePdfData() -> NSMutableData {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
        self.prepare(forDrawingPages: NSMakeRange(0, self.numberOfPages))
        let printRect = UIGraphicsGetPDFContextBounds()
        for pdfPage in 0..<self.numberOfPages {
            UIGraphicsBeginPDFPage()
            self.drawPage(at: pdfPage, in: printRect)
        }
        UIGraphicsEndPDFContext();
        return pdfData
    }
}

Es speichert die Datei PDF im Verzeichnis und gibt den Pfad der PDF-Datei zurück.

0
Ashish Chauhan