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

如何使用RTF Parser Kit提取RTF中的内嵌图片到File列表?

问题描述

我从SQL Server数据库中读取某列的RTF格式数据,目前已经用RTF Parser Kit成功将RTF转换为纯文本,代码如下:

InputStream is = new ByteArrayInputStream(input.getBytes());
StringTextConverter converter = new StringTextConverter();
converter.convert(new RtfStreamSource(is));
input = converter.getText();

但部分RTF内容里包含内嵌图片,请问能不能用RTF Parser Kit把这些图片提取到ArrayList<File> files = new ArrayList<>();中?

示例图片:
示例图片

对应的RTF片段(完整内容过长,仅展示部分):

{\rtf1\ansi\ansicpg1253\uc1\deff1\adeff1\deflang0\deflangfe0\adeflang0{\fonttbl
{\f0\fswiss\fcharset0\fprq2{\*\panose 020B0604020202020204}Arial;}
{\f1\fswiss\fcharset161\fprq2 Arial Greek;}
{\f2\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}}
{\colortbl;\red0\green0\blue0;}
{\stylesheet{\s0\ltrpar\itap0\nowidctlpar\ql\li0\ri0\lin0\rin0\cbpat0\rtlch\af1\afs24\ltrch\f1\fs24 [Normal];}{\*\cs10\additive Default Paragraph Font;}}
{\info
{\*\txInfo{\txVer 24.0.712.500}}}
\paperw12240\paperh15840\margl1138\margt1138\margr1138\margb1138\deftab1134\widowctrl\lytexcttp\formshade\sectd
\headery567\footery567\pgwsxn12240\pghsxn15840\marglsxn1138\margtsxn1138\margrsxn1138\margbsxn1138\pgbrdropt32\pard\ltrpar\itap0\nowidctlpar\ql\li0\ri0\lin0\rin0\plain\rtlch\af0\afs20\alang1033\ltrch\f0\fs20\lang1033\langnp1033\langfe1033\langfenp1033 Hello, \par\par This is an example!\par\par
{\shp{\*\shpinst\shpleft0\shptop0\shpright7500\shpbottom3450\shpfhdr0\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr2\shpwrk0\shpz0\shplid1025{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn wzName}{\sv _tx_id_1_}}{\sp{\sn pib}{\sv {\pict\jpegblip\picw13229\pich6085\picwgoal7500\pichgoal3450\picscalex100\picscaley100 
ffd8ffe000104a46494600010101006000600000ffe101024578696600004d4d002a000000080007011a0005000000010000
0062011b0005000000010000006a012800030000000100020000013100020000001100000072013b00020000000700000084
ff0011dbd85aebb65a6ead089ededb55b7d2f51d5b4f8af6253b654b4d4af61071b6e24fbc403d62800a002800a002800a00
2800a002800a002800a002800a002800a002800a002800a002800a002800a002800a002800a002800a002800a002800a0028
00a002800a002800a002800a002800a002800a002803ffd9}}}\par }
解决方案

可以用RTF Parser Kit提取内嵌图片,核心思路是自定义Converter,重写图片处理方法,解析图片数据并保存为文件后加入目标ArrayList。

步骤1:自定义图片提取转换器

继承StringTextConverter,保留原文本转换功能的同时添加图片存储逻辑:

import com.rtfparserkit.parser.IRtfParser;
import com.rtfparserkit.parser.RtfParser;
import com.rtfparserkit.parser.IRtfSource;
import com.rtfparserkit.converter.StringTextConverter;
import com.rtfparserkit.rtf.Command;
import com.rtfparserkit.rtf.RtfPictureData;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class RtfTextAndImageConverter extends StringTextConverter {
    private List<File> imageFiles;
    private File outputDir;

    // 初始化时指定图片输出目录和存储列表
    public RtfTextAndImageConverter(File outputDir, List<File> imageFiles) {
        this.outputDir = outputDir;
        this.imageFiles = imageFiles;
        // 创建输出目录(不存在则自动生成)
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
    }

    // 重写处理图片的方法
    @Override
    public void processPicture(RtfPictureData pictureData) {
        super.processPicture(pictureData); // 保留原文本转换的占位逻辑(可选)

        // 获取图片格式和原始二进制数据
        Command pictureType = pictureData.getType();
        byte[] imageBytes = pictureData.getData();

        // 根据RTF图片命令匹配对应文件后缀
        String fileExt = switch (pictureType.getCommandName()) {
            case "jpegblip" -> ".jpg";
            case "pngblip" -> ".png";
            case "emfblip" -> ".emf";
            case "wmfblip" -> ".wmf";
            default -> ".bin"; // 未知格式用通用后缀
        };

        // 生成唯一文件名,避免重复覆盖
        String fileName = "rtf_image_" + System.currentTimeMillis() + fileExt;
        File imageFile = new File(outputDir, fileName);

        // 写入图片数据到本地文件
        try (FileOutputStream fos = new FileOutputStream(imageFile)) {
            fos.write(imageBytes);
            imageFiles.add(imageFile); // 将生成的文件对象加入目标列表
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

步骤2:使用自定义转换器处理RTF

替换原有的StringTextConverter,传入图片输出目录和目标ArrayList即可完成文本转换+图片提取:

public static void main(String[] args) throws IOException {
    String rtfContent = "从SQL Server读取的RTF字符串"; // 替换为实际获取的RTF内容
    List<File> files = new ArrayList<>();
    File imageOutputDir = new File("./extracted_images"); // 自定义图片保存目录

    InputStream is = new ByteArrayInputStream(rtfContent.getBytes());
    IRtfSource source = new com.rtfparserkit.parser.RtfStreamSource(is);
    
    RtfTextAndImageConverter converter = new RtfTextAndImageConverter(imageOutputDir, files);
    IRtfParser parser = new RtfParser();
    parser.parse(source, converter);

    // 获取转换后的纯文本
    String plainText = converter.getText();
    // 查看提取到的图片列表
    System.out.println("共提取到" + files.size() + "张图片");
    for (File f : files) {
        System.out.println("图片路径:" + f.getAbsolutePath());
    }
}

注意事项

  • 确保使用RTF Parser Kit的最新稳定版,避免版本兼容问题
  • 遇到未知图片格式时,可根据实际需求扩展格式匹配逻辑
  • 文件名生成规则可结合业务场景调整(比如加入图片在RTF中的位置标识)
  • 需完善IO异常处理逻辑,避免因文件写入失败导致程序中断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:05:24