当前位置: 首页 > article >正文

复杂html动态页面高还原批量导出方案

复杂html动态页面高还原批量导出方案

    • 方案一
    • 方案二

方案一

  • thymeleaf

thymeleaf 负责服务端渲染,输出html静态页面。

  • wkhtmltopdf

wkhtmltopdf 是一个基于 WebKit 的命令行工具,能够将 HTML 转换为 PDF。
支持复杂的 HTML 和 CSS。
缺点

  1. wkhtmltopdf软件需要提前安装,增加系统部署复杂度。
  2. WebKit引擎的渲染结果和浏览器有差异,可能需要调整html的兼容性。
  • 其它

服务端缓存导出记录,下次导出同一份数据,直接命中对象存储中的文件。

        <!-- Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    public void generatePdf() throws Exception {
        // Create the Thymeleaf context and set variables
        Context context = new Context();
        MyData data = myService.queryData(100L);
        context.setVariable("data", data);

        // Process the Thymeleaf template
        String htmlContent = templateEngine.process("report", context);

        FileUtil.writeUtf8String(htmlContent, "D:/data/tmp/input.html");

        // 调用 wkhtmltopdf 命令行工具
        Process process = Runtime.getRuntime().exec("D:/Program Files/wkhtmltopdf/bin/wkhtmltopdf D:/data/tmp/input.html D:/data/tmp/output.pdf");
        process.waitFor();
    }

针对缺点2,可以使用Cursor AI辅助编码工具,一键改写。

  • prompt
[任务背景]
需要将HTML文档通过wkhtmltopdf(v0.12.6+)转换为PDF。由于该工具基于Qt WebKit引擎,请确保生成的HTML/CSS严格遵循其兼容性要求。

[核心要求]
1. 代码必须完全兼容wkhtmltopdf的渲染限制
2. 保持原有布局的视觉一致性
3. 优先使用经wkhtmltopdf验证的替代方案
4. 输出可维护的简洁代码

[技术限制清单]
## 布局系统
- 禁用:Flexbox/Gap属性、CSS Grid、Multi-column布局
- 替代方案:表格布局(table-layout)/浮动定位(float)/绝对定位
- 间距控制:使用margin/padding代替gap属性

## CSS特性
- 禁用:CSS变量(var())、position:sticky、clip-path等新特性
- 选择器:仅支持CSS2.1基础选择器,避免:nth-child等伪类
- 盒模型:明确指定width/height,避免calc()等动态计算

## 渲染特性
- 禁用:所有CSS动画/过渡效果、3D变换
- 伪元素:限制::before/::after的使用,避免复杂内容生成
- 字体:必须嵌入base64字体,禁用woff2格式

[优化策略]
1. 布局重构:使用基于浮动的布局系统(table布局作为备选方案)
2. 样式降级:将CSS变量替换为静态值,合并重复样式
3. 渐进增强:为关键元素添加兼容层(如通过JS计算布局)
4. 输出规范:生成带版本注释的代码,标注兼容性处理点

方案二

selenium-java
优点: 使用真实的Chrome浏览器渲染,高还原度。
缺点

  1. 需要安装Chrome浏览器Chrome驱动,并要保证两者的兼容性,增加系统部署复杂度。
    <!-- Selenium 主库 -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.15.0</version>
    </dependency>
    
    <!-- 强制指定 Guava 版本 -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>32.1.2-jre</version>
    </dependency>
</dependencies>
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v114.page.Page;
import org.openqa.selenium.devtools.v114.page.model.PrintToPDFTransferMode;
import java.util.Base64;
import java.util.Optional;
import java.nio.file.Files;
import java.nio.file.Paths;

public class PdfExporter {

    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
        
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new");
        options.addArguments("--disable-gpu");
        options.addArguments("--force-device-scale-factor=1"); // 防止缩放
        
        WebDriver driver = new ChromeDriver(options);
        DevTools devTools = ((ChromeDriver) driver).getDevTools();

        try {
            devTools.createSession();
            devTools.send(Page.enable());

            driver.get("https://example.com");
            Thread.sleep(2000);

            // 完整参数配置(按方法定义顺序)
            String pdfData = devTools.send(
                Page.printToPDF(
                    Optional.of(false),               // landscape
                    Optional.of(false),              // displayHeaderFooter
                    Optional.of(true),               // printBackground
                    Optional.of(1.0),                // scale
                    Optional.of(8.5),                // paperWidth (inches)
                    Optional.of(11.0),               // paperHeight (inches)
                    Optional.of(0.4),                // marginTop
                    Optional.of(0.4),                // marginBottom
                    Optional.of(0.4),                // marginLeft
                    Optional.of(0.4),                // marginRight
                    Optional.empty(),                // pageRanges (默认全部)
                    Optional.empty(),                // headerTemplate
                    Optional.empty(),                // footerTemplate
                    Optional.of(true),               // preferCSSPageSize
                    Optional.of(PrintToPDFTransferMode.RETURNASBASE64) // transferMode
                )
            ).getData();

            Files.write(Paths.get("output.pdf"), Base64.getDecoder().decode(pdfData));
            System.out.println("PDF生成成功");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            driver.quit();
        }
    }
}

http://www.kler.cn/a/566650.html

相关文章:

  • 微服务即时通信系统---(六)语音识别子服务
  • 【Java】Spring Boot全量YAML配置说明
  • 爬虫获取 item_get 接口:获得VIP商品详情的完整指南
  • Java语言Leetcode中常用的一些基础语法
  • 性能测试测试策略制定|知名软件测评机构经验分享
  • 经典算法 统计数字问题(常数时间解决)
  • LeetCode 热门100题-除自身以外数组的乘积
  • 【原创】Ubuntu 24搭建Ollama+ DeepSeek局域网服务器
  • 不同Embedding模型与大语言模型(LLM)的交互主要通过语义向量传递实现
  • 对泰坦尼克号沉没事件幸存者数据分析和预测
  • 如何用python画一棵分形树
  • [C++] enum 以及 enum class 简单用法
  • 一文掌握Splash的详细使用
  • QT Creator添加延迟的方法
  • 爬取网易云歌单信息并分析
  • 有向图的拓扑排序-BFS求解
  • 如何选择DevOps平台?GitHub、GitLab、BitBucket、Jenkins对比与常见问题解答
  • javascript经典练习题-语法与特性
  • word转换为pdf后图片失真解决办法、高质量PDF转换方法
  • HTML 基础 (快速入门)详细步骤和示例