简体   繁体   中英

Download image returned by JavaScript (html2canvas)

I'm trying to download an image from a WebPage, which is returned by a JavaScript (using html2canvas) immediately after calling it. Therefore I'm using the library HTMLUnit, but I haven't been successful until now.

Unfortunately only a faulty png-File is downloaded, which has around 140kb. It can't be opened by Windows (eg paint or preview).

Code-Snippet for my HTML-Page (executed immediately after div-element #div is loaded:

function saveMap() {
    var element = $("#div");

    html2canvas(element, {
        useCORS: true,
        onrendered: function(canvas) {
            var dataUrl= canvas.toDataURL("image/png");

            var a = $("<a>")
                .attr("href", dataUrl)
                .attr("download", "test.png")
                .appendTo("body");

            a[0].click();

            a.remove();
        }
    });
}

Java-Code trying to download the returned png-File:

WebClient webClient = new WebClient(BrowserVersion.CHROME);

try {
    HtmlPage page1 = webClient.getPage( new URI("file:///D:/path/to/page/sample.html").toURL() );
    webClient.waitForBackgroundJavaScript(5000);


    InputStream is = page1.getWebResponse().getContentAsStream();

    File f = new File("test.png");
    OutputStream os = new FileOutputStream(f);
    byte[] bytes = new byte[2048];

    int b = 0;

    while ((b = is.read()) != -1)
    {
        os.write(bytes, 0, b);
    }

    os.close();
    is.close();
} catch (FailingHttpStatusCodeException | IOException | URISyntaxException e) {
    e.printStackTrace();
}

Full HTML-Page:

<!DOCTYPE html>
<html>
    <head>
    <style>
    html, body, #div {
        height: 100%;
        width: 100%;
        margin: 0px;
        padding: 0px
    }
    </style>
    <script src="html2canvas.js"></script>
    <script type="text/javascript" src="jquery-3.2.1.min.js"></script>

    </head>
    <body>
    <div id="div"></div>
        <script>
            // Some init stuff for div and after completion the following:
            saveMap();

        function saveMap() {

            var element = $("#div");

            html2canvas(element, {
                useCORS: true,
                onrendered: function(canvas) {
                    var dataUrl= canvas.toDataURL("image/png");

                    var a = $("<a>")
                        .attr("href", dataUrl)
                        .attr("download", "test.png")
                        .appendTo("body");

                    a[0].click();

                    a.remove();
                }
            });
        }
        </script>
    </body>
</html>

Thanks for the code. Have already done some tests with the samples available on the html2canvas web page. There is bug in the current version of HtmlUnit that stops the javascript from working. I think i have done a fix also, but sourceforge is down at the moment. If they are back i will commit the fix and prepare a new snapshot. Will inform you and also have a look at your sample.

BTW: Do not expect nice screenshots from this. HtmlUnit is a headless browser and most of the layout functions are doing only a basic job. But you are welcome to provide better implementations.

Your code works (with some fixes) with the latest snapshot. But to get reasonable results you have to provide a width and height for the result. I guess there is some layouting in HtmlUnit that returns otherwise 1x1 as result size. If this is a problem for you might have a look inside the code and try to point to the problematic place.

        html2canvas(element, {
            useCORS: true,
            width: 300,
            height: 300,
            onrendered: function(canvas) {

Now to your java code

HtmlPage page1 = webClient.getPage( new URI("file:///D:/path/to/page/sample.html").toURL() );
webClient.waitForBackgroundJavaScript(5000);

The tricky part here is the async execution of the rendering inside your browser. From HtmlUnit point of view the browsers will, after the loading of the page was done, replace the content of the current window with the png image. Andd you have to deal with this in your code. Because there is a replace your page1 is still the old page returned (sync). After the wait you have to reget the current content to have the png in hands

        Page image = webClient.getCurrentWindow().getEnclosedPage();
        InputStream is = image.getWebResponse().getContentAsStream();

And finally there is a small issue with your image writing code Instead of

while ((b = is.read()) != -1)

you have to write

while ((b = is.read(bytes)) != -1)

Otherwise you will end up with a file of null bytes.

Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM