【问题标题】:Download image returned by JavaScript (html2canvas)下载 JavaScript 返回的图片 (html2canvas)
【发布时间】:2018-03-08 09:07:39
【问题描述】:

我正在尝试从网页下载图像,该图像在调用后立即由 JavaScript(使用 html2canvas)返回。因此我使用了HTMLUnit库,但直到现在我还没有成功。

不幸的是,只下载了一个错误的 png 文件,大约 140kb。 Windows 无法打开它(例如绘制或预览)。

我的 HTML 页面的代码片段(在 div-element #div 加载后立即执行:

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 尝试下载返回的 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();
}

完整的 HTML 页面:

<!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>

【问题讨论】:

  • 能否请您添加完整的示例 html 页面。
  • 刚刚将完整的 html 源代码添加到我的初始帖子中。 HTML页面应该没有问题,因为当我通过普通浏览器(例如Chrome)调用它时,下载工作正常并且图像很好。

标签: javascript java html htmlunit html2canvas


【解决方案1】:

感谢您的代码。已经使用 html2canvas 网页上提供的示例进行了一些测试。当前版本的 HtmlUnit 中存在阻止 javascript 工作的错误。 我想我也做了修复,但 sourceforge 目前已经关闭。如果他们回来了,我将提交修复并准备新的快照。会通知您并查看您的样品。

顺便说一句:不要期望从中得到漂亮的屏幕截图。 HtmlUnit 是一个无头浏览器,大多数布局功能只做一个基本的工作。但欢迎您提供更好的实现。

【讨论】:

  • 哦,那太好了。我不需要漂亮的截图,低质量就可以了:)
  • 已经做了一些测试。到目前为止,它适用于最新的 html2canvas 版本,但不适用于较新的基于 Promise 的 beta 版本。现在必须集中精力使新的 HtmlUnit 版本可用。你使用这个较新的 html2canvas 版本吗?
  • 我正在使用 html2canvas 0.5.0-beta3 和 HtmlUnit 2.27。我不认为 html2canvas 是问题,因为下载可以在普通浏览器(例如 chrome)中运行,但不能使用 HtmlUnit(可能我的源代码错误 - 我不知道)
  • 有一个误会,我不认为html2canvas 是问题,但是当前版本的HtmlUnit 与最新的html2canvas 的东西有问题。将查看并尝试解决此问题,但这需要一些时间。请为此问题打开一个问题,否则这可能会在大量的想法中丢失。
  • 我刚刚在 sourceforge 上开了一张票。我会尝试这两个库的旧版本,也许这是有效的——如果我成功了,我会告诉你的。我的硕士论文需要这些东西,这就是我寻找“快速”解决方案的原因;)
【解决方案2】:

您的代码适用于最新的快照(有一些修复)。 但要获得合理的结果,您必须为结果提供宽度和高度。我猜 HtmlUnit 中有一些布局会返回 1x1 作为结果大小。如果这对您来说是个问题,您可以查看代码内部并尝试指出有问题的地方。

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

现在到你的 java 代码

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

这里的棘手部分是在浏览器中异步执行渲染。从 HtmlUnit 的角度来看,浏览器会在页面加载完成后,用 png 图像替换当前窗口的内容。而且你必须在你的代码中处理这个问题。因为有一个替换您的 page1 仍然是返回的旧页面(同步)。 等待后,您必须重新获取当前内容才能拥有 png

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

最后,您的图像编写代码存在一个小问题 而不是

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

你必须写

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

否则你会得到一个空字节的文件。

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    相关资源
    最近更新 更多