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

Java实现PDF转SVG并保留可编辑文本的方法咨询

Java实现PDF转SVG并保留文本内容的方法

你可以通过调整工具使用方式或换用更直接的PDF解析方案实现,以下是具体方法:

方法一:使用Apache PDFBox的SVGConverter类(推荐)

PDFBox提供了专门的SVG转换工具,能直接解析PDF中的文本元素并生成保留文本的SVG,无需依赖打印流程。示例代码如下:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.tools.SVGConverter;

import java.io.File;
import java.io.IOException;

public class PdfToSvgWithText {
    public static void main(String[] args) throws IOException {
        try (PDDocument document = PDDocument.load(new File("input.pdf"))) {
            SVGConverter converter = new SVGConverter();
            // 设置输出目录,每个页面生成单独的SVG文件
            converter.setOutputDir(new File("output_svgs"));
            // 显式关闭文本转路径,确保保留文本元素
            converter.setRenderTextAsPath(false);
            converter.convert(document);
        }
    }
}

需确保使用PDFBox 2.0及以上版本,该工具会直接解析PDF的文本对象,将其转换为SVG的<text>元素,而非路径。

方法二:自定义PDF文本提取+Batik生成SVG

如果需要更精细的控制,可以手动提取PDF中的文本及其位置、字体信息,再用Batik的SVGGraphics2D直接绘制文本:

  1. 继承PDFBox的PDFTextStripper,重写方法提取文本的坐标、内容、字体大小等信息
  2. 初始化SVGGraphics2D,根据提取的信息调用drawString()绘制文本
  3. 导出SVG文件

示例简化代码:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import org.apache.batik.svggen.SVGGraphics2D;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.svg.SVGFactory;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CustomPdfToSvg {
    static class TextInfo {
        String content;
        float x;
        float y;
        float fontSize;
        String fontName;

        public TextInfo(String content, float x, float y, float fontSize, String fontName) {
            this.content = content;
            this.x = x;
            this.y = y;
            this.fontSize = fontSize;
            this.fontName = fontName;
        }
    }

    public static void main(String[] args) throws Exception {
        List<TextInfo> textInfos = new ArrayList<>();
        try (PDDocument document = PDDocument.load(new File("input.pdf"))) {
            PDFTextStripper stripper = new PDFTextStripper() {
                @Override
                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                    for (TextPosition tp : textPositions) {
                        textInfos.add(new TextInfo(
                                tp.getUnicode(),
                                tp.getX(),
                                document.getPage(0).getMediaBox().getHeight() - tp.getY(),
                                tp.getFontSizeInPt(),
                                tp.getFont().getName()
                        ));
                    }
                }
            };
            stripper.setStartPage(1);
            stripper.setEndPage(1);
            stripper.getText(document);

            // 初始化SVG生成器
            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
            SVGFactory factory = ((org.w3c.dom.svg.SVGDOMImplementation) registry.getDOMImplementation("SVG"))
                    .createSVGFactory();
            SVGDocument svgDoc = factory.createSVGDocument("http://www.w3.org/2000/svg");
            SVGGraphics2D svgGenerator = new SVGGraphics2D(svgDoc);

            // 绘制文本
            for (TextInfo info : textInfos) {
                svgGenerator.setFont(new java.awt.Font(info.fontName, java.awt.Font.PLAIN, (int) info.fontSize));
                svgGenerator.drawString(info.content, info.x, info.y);
            }

            // 导出SVG
            try (FileWriter writer = new FileWriter("output.svg")) {
                svgGenerator.stream(writer, true);
            }
        }
    }
}

这种方式需要处理字体映射、坐标转换等细节,适合需要自定义文本样式的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:55:18