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

带SVG的HTML转PDF问题排查及Lubuntu打印工具咨询

问题解决方案:SVG转PDF的两种路径(Flying Saucer修复 + 浏览器引擎替代)

一、解决Flying Saucer不显示SVG转图片的问题

你遇到的核心问题确实是Flying Saucer对data:image/svg+xml格式的支持有限——虽然它能处理data URI,但内置的资源处理器只对PNG/JPG这类位图格式友好,不会主动解析SVG的data URI并渲染成图片。这里有两个可行的修复方向:

1. 前端提前把SVG转成PNG的data URI

把你原来的SVG替换逻辑改成用Canvas将SVG渲染成PNG,再生成PNG的data URI,这样Flying Saucer就能正常识别了。代码示例:

var $body_clone = $('#pdf_container').clone();
var $svgs = $body_clone.find('svg');

// 用Promise处理异步的图片加载和Canvas渲染
Promise.all($svgs.map(function(index, svgEl) {
  return new Promise((resolve) => {
    const $svg = $(svgEl);
    const xml = new XMLSerializer().serializeToString(svgEl);
    const svgDataUri = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(xml)));
    
    const img = new Image();
    img.onload = function() {
      // 创建Canvas绘制SVG
      const canvas = document.createElement('canvas');
      canvas.width = $svg.outerWidth(true);
      canvas.height = $svg.outerHeight(true);
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      
      // 导出为PNG的data URI并替换原SVG
      const pngDataUri = canvas.toDataURL('image/png');
      const $img = $(`<img src="${pngDataUri}" width="${canvas.width}" height="${canvas.height}">`);
      $svg.replaceWith($img);
      resolve();
    };
    img.src = svgDataUri;
  });
})).then(() => {
  // 这里执行表单提交,把$body_clone的HTML发给服务器
});

2. 服务器端用Batik转换SVG为PNG

如果前端转换遇到跨域、SVG引用外部资源等问题,可以把SVG的XML内容传到服务器,用Apache Batik(专门处理SVG的Java库)转成PNG,再生成data URI插入模板:

import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Base64;

public String svgToPngDataUri(String svgXml) {
  PNGTranscoder transcoder = new PNGTranscoder();
  try (ByteArrayInputStream in = new ByteArrayInputStream(svgXml.getBytes());
       ByteArrayOutputStream out = new ByteArrayOutputStream()) {
    TranscoderInput input = new TranscoderInput(in);
    TranscoderOutput output = new TranscoderOutput(out);
    transcoder.transcode(input, output);
    
    byte[] pngBytes = out.toByteArray();
    return "data:image/png;base64," + Base64.getEncoder().encodeToString(pngBytes);
  } catch (Exception e) {
    throw new RuntimeException("Failed to convert SVG to PNG", e);
  }
}

二、关于Lubuntu上Firefox打印PDF的工具与替代方案

你用Firefox打印PDF效果完美,是因为它用的是Gecko引擎自身的页面渲染+PDF生成逻辑,在Linux下可能会借助系统的CUPS打印服务,但核心渲染还是Firefox自己做的。如果想复用这个能力,最直接的方式是用无头模式的Firefox作为外部转换器:

1. 用Headless Firefox生成PDF

这是最省心的方案,能完全复现你手动打印的效果,命令行调用示例:

# 生成在线页面的PDF
firefox --headless --print-to-pdf="/tmp/output.pdf" "https://your-app.com/pdf-page"

# 生成本地HTML文件的PDF
firefox --headless --print-to-pdf="/tmp/output.pdf" "file:///path/to/your-generated-page.html"

如果要在Java服务中集成,可以用ProcessBuilder执行这个命令,然后读取生成的PDF文件返回给客户端。

2. 原理说明

Firefox的无头模式会完整加载页面,解析所有CSS、SVG和JavaScript,然后将渲染后的页面转换成PDF——和你手动点击打印的流程完全一致,所以能保证样式和交互(如果有的话)的完美还原,这比Flying Saucer这类纯Java的HTML转PDF工具对现代Web特性的支持好得多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:43:42