word与html互转(1) -- word转html

使用忠告

使用该方式进行xhtml到word的转换, 简单转换是可以, 但是可能并没有想象中那么满意, 转换出来的word格式并不完美, 比如目录和标题都会丢失, 标题显示看起来一样, 但是是用正文加粗和加大字号来显示的. 毕竟word是一种文档格式, 而html是一种标记性语言, 要想实现完美兼容和转换很难

加上word与html互转(2) -- html转word, 虽然word与html互转都有实现手段, 但是考虑到转换的格式复杂度和后期的维护成本, 我们最后放弃去实现这个成本高但是对项目影响不大的功能

其中word转html功能实现中, 转出的html的格式并没有想象中的好, 某些样式是通过class样式来显示的, 并不全是行内样式, 并且html所有文本标签都是使用的p标签, 包括标题.

实现

实现方式

我在网上搜集了很多实现方式, 各式各样的, 最后我决定使用poi+xdocreport来实现
poi都熟悉, 这边我不作介绍
xdocreport是github上的一个开源项目, 他的具体介绍可以去他的项目地址查看--项目地址, 选择这个开源项目主要有以下几个原因:
    1. 他是开源的(免费)
    2项目本身模块化, 我们可以只引用需要的功能(轻量化)
    3.转换是基于poi的转换进行补充扩展的,感觉比poi原生的更好一些(emm...没验证)
    4.使用简单便捷
这里只使用了xdocreport的转换器功能, 可以点这里直接查看对应的wiki

引入相关程序包

 <dependency>
  <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>3.14</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.14</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>3.14</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.3</version>
</dependency>

docx转html

    public static void main(String[] args) {
        String fileInName = "test.docx";
        XWPFDocument document = null;
        try {
            document = new XWPFDocument(new FileInputStream(fileInName));
            XHTMLOptions options = XHTMLOptions.create();
            options.setImageManager( new ImageManager(new File(""), "") {

                @Override
                public void extract(String imagePath, byte[] imageData) throws IOException {
                    System.out.println("这里上传图片到图片服务器");
                }

                @Override
                public String resolve(String uri) {
                    return "https://csdnimg.cn/pubfooter/images/csdn_cs_qr.png";
                }

            });
            StringWriter stringWriter = new StringWriter();
//            XHTMLConverter.getInstance().convert( document, out, options );
            XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
            xhtmlConverter.convert(document, stringWriter, options);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

上面我自己写的示例跟官方的示例有所区别, 下面我贴出官方示例然后在进行解释

/**
 * 官方示例
 */
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;

...

// 1) Load DOCX into XWPFDocument
InputStream in= new FileInputStream(new File("HelloWord.docx"));
XWPFDocument document = new XWPFDocument(in);

// 2) Prepare XHTML options (here we set the `ImageManager` to store image and resolve iamge src)
XHTMLOptions options = XHTMLOptions.create().setImageManager( new ImageManager( new File(root), "images" ) );

// 3) Convert XWPFDocument to XHTML
OutputStream out = new FileOutputStream(new File("HelloWord.htm"));
XHTMLConverter.getInstance().convert(document, out, options);

跟官方不一样的地方的解释
1.在给XHTMLOption设置图片管理器对象的时候
官方是直接设置了一个图片路径, 生成的html里面的图片引用指向的是设 置的路径, 而我这边有专门的文件服务器, 所以需要将里面的图片上传到图片服务器中, 然后将html中图片的引用指向文件服务器, 所以我重写了图片管理器的代码, 将其中保存图片和给html中图片引用换成了自己的实现

XHTMLOptions options = XHTMLOptions.create();
options.setImageManager( new ImageManager(new File(""), "") {

    @Override
    public void extract(String imagePath, byte[] imageData) throws IOException {
        System.out.println("这里上传图片到图片服务器");
    }

    @Override
    public String resolve(String uri) {
        return "https://csdnimg.cn/pubfooter/images/csdn_cs_qr.png";
    }

});

2.转换并保存html的时候
官方示例是将html保存成文件到一个路径下面, 而我的需求并不是保存文件, 而是要将生成的html分段下沉到DB, 所以可以在这里

    StringWriter stringWriter = new StringWriter();
    XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
    xhtmlConverter.convert(document, stringWriter, options);

将官方示例的文件输出流换成自己的StringWriter就可以了(你也可以换成自己需要的流), 我这样替换就可以拿到html的字符串, 接着就可以使用jsoup进行html的解析并分段存储了

doc转html

public String doc2html() throws Exception {
    HWPFDocument hwpfDocument = new HWPFDocument(new FileInputStream("test.doc"));

    Document newDocument = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument();
    WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(newDocument);

    wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> {
        //content是图片内容, 这里将图片保存到图片服务器, 然后将保存的图片路径返回
        //同样, 你也可以将图片保存到本地相对路径, 然后将相对路径返回, html也能正常显示图片
        return "https://csdnimg.cn/pubfooter/images/csdn_cs_qr.png";
    });

    wordToHtmlConverter.processDocument(hwpfDocument);

    Transformer transformer = TransformerFactory.newInstance()
                .newTransformer();
    //指定Transformer在输出结果树时是否可以添加额外的空格
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    //指定输出编码
    transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
    transformer.setOutputProperty(OutputKeys.METHOD, "html");

    //这里是希望将转换后的流最终输出到字符串进行返回, 如果你希望直接输出文件, 你可以创建一个文件流放进下面的参数
    StringWriter stringWriter = new StringWriter();
    transformer.transform(new DOMSource(wordToHtmlConverter.getDocument()), new StreamResult(stringWriter));

    return stringWriter.toString();
}

示例代码比较简单, 但是已经具备转换的功能, 需要注意和可能变动的点我在代码注释中已经说明, 可以根据需求来修改图片的保存和最后输出的结果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 程序设计需要将各种需要模拟计算的内容抽象为数字。 通常采用二维数组表示2D地图 又以不同的数字代表地图上不同类型的...
    Godan阅读 2,055评论 0 1
  • 博客链接:http://www.ideabuffer.cn/2017/05/07/理解CPU-Cache/ CPU...
    闪电是只猫阅读 3,030评论 2 14
  • 作为大学生。对于我来说,这是第一个,让我觉得无聊的假期。 怎么说呢,以前放假,基本上是游戏填充了所有时光,并不觉得...
    我懂xxhhz了阅读 176评论 0 0
  • 躲在空无一人的楼顶晒太阳,心头的悲伤都随着阳光荡漾。我嗅出城市的朽烂被蒸发的味道,那个黑暗的影子, 在我的右边模仿...
    栗子_栗子阅读 490评论 4 5
  • 问题严重!中国老龄化调查报告 这条音频给你分享一份,中国老龄化调查报告。 大家都知道,中国老龄化的现象是越来越严重...
    嗨嗨皮皮的阅读 715评论 0 2