You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java使用HTMLUnit+html2canvas生成图片报Cannot modify readonly property错误

核心问题定位

  1. HTMLUnit 2.5.2 版本过老,对现代JS语法、原生对象属性操作的兼容性极差,是触发Cannot modify readonly property: constructor报错的直接原因
  2. 资源获取逻辑错误:html2canvas生成的图片是前端JS运行时动态生成的,不存在于初始页面的响应流中,直接读取当前窗口页面的响应流得到的是原始HTML内容,存为png自然是损坏空白文件

快速解决方案

按优先级执行以下操作:

  • 优先升级HTMLUnit到最新稳定版,老旧版本对html2canvas这类现代前端库的兼容缺陷极多,升级后可以直接解决90%的原生对象属性只读报错
  • 若暂时无法升级版本,在加载目标页面前提前注入JS补丁,开放对应原生对象的constructor写入权限:
WebClient webClient = new WebClient(BrowserVersion.CHROME);
// 原有配置保留
webClient.getOptions().setCssEnabled(true);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
// 新增注入补丁
webClient.executeJavaScript("""
    Object.defineProperty(HTMLOptionElement.prototype, 'constructor', { writable: true });
    Object.defineProperty(MutationObserver.prototype, 'constructor', { writable: true });
    Object.defineProperty(URL.prototype, 'constructor', { writable: true });
""");
  • 修正图片获取逻辑,不要直接读取当前页面响应流,等JS运行完成后执行页面JS拿到动态生成的图片base64内容再解码存储:
URL url = new URL(targetUrl);
HtmlPage htmlPage = webClient.getPage(url);
// 新增视口配置,避免html2canvas渲染空视口导致空白图,尺寸可根据实际渲染需求调整
htmlPage.getEnclosingWindow().setOuterWidth(1920);
htmlPage.getEnclosingWindow().setOuterHeight(1080);
// 延长等待时间确保渲染完成
webClient.waitForBackgroundJavaScript(10000); 
// 执行JS获取生成的图片base64,选择器可根据页面实际结构调整
String base64Content = (String) htmlPage.executeJavaScript("return document.querySelector('#生成的canvas或者img元素的选择器').toDataURL('image/png').split(',')[1]").getJavaScriptResult();
// 解码base64写文件
byte[] imgBytes = Base64.getDecoder().decode(base64Content);
try (OutputStream os = new FileOutputStream(new File(path + "/generatedPic.png"))) {
    os.write(imgBytes);
}

内容的提问来源于stack exchange,提问作者m3_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:39:02