Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
722 views
in Technique[技术] by (71.8m points)

html - UIMarkupTextPrintFormatter never renders base64 images

Im creating a pdf file out of html content in swift 3.0:

/**
 *
 */
func exportHtmlContentToPDF(HTMLContent: String, filePath: String) {
    // let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 694, height: 603));

    // webView.loadHTMLString(HTMLContent, baseURL: nil);

    let pdfPrinter = PDFPrinter();
    let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent);
    // let printFormatter = webView.viewPrintFormatter();

    pdfPrinter.addPrintFormatter(printFormatter, startingAtPageAt: 0);

    let pdfData = self.drawPDFUsingPrintPageRenderer(printPageRenderer: pdfPrinter);

    pdfData?.write(toFile: filePath, atomically: true);
}

/**
 *
 */
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
    let data = NSMutableData();

    UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil);

    printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages));

    let bounds = UIGraphicsGetPDFContextBounds();

    for i in 0...(printPageRenderer.numberOfPages - 1) {
        UIGraphicsBeginPDFPage();

        printPageRenderer.drawPage(at: i, in: bounds);
    }

    UIGraphicsEndPDFContext();

    return data;
}

Everything is rendered fine except my base64 encoded images. The HTML content itself in a webview or inside safari or chrome browser is presented correctly and is showing all images correctly. But the images are never rendered into the pdf.

Why are the images not rendered and how can I get them to be rendered?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This happens because WebKit first parses the HTML into a DOM, and renders content on multiple event loop cycles. You therefore need to wait for not just the page DOM to be ready but for the resource loading to be complete. As you also suggest, you need to refactor your code such that the webview gets loaded first, and you only then export its contents.

To determine the correct time to fire the export, you can observe for the state of the DOM document in the web view. There are multiple ways to do this, but the most readable option I find is a port of an answer to a related Objective-C question: in your UIWebViewDelegate implementation, implement webViewDidFinishLoad in the following way to monitor document.readyState:

    func webViewDidFinishLoad(_ webView: UIWebView) {

        guard let readyState = webView.stringByEvaluatingJavaScript(from: "document.readyState"),
            readyState == "complete" else
        {
            // document not yet parsed, or resources not yet loaded.
            return
        }

        // This is the last webViewDidFinishLoad call --> export.
        //
        // There is a problem with this method if you have JS code loading more content:
        // in that case -webViewDidFinishLoad can get called again still after document.readyState has already been in state 'complete' once or more.
        self.exportHtmlContentToPDF(…)
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...