word與html互轉(zhuǎn)(1) -- word轉(zhuǎn)html

使用忠告

使用該方式進(jìn)行xhtml到word的轉(zhuǎn)換, 簡單轉(zhuǎn)換是可以, 但是可能并沒有想象中那么滿意, 轉(zhuǎn)換出來的word格式并不完美, 比如目錄和標(biāo)題都會(huì)丟失, 標(biāo)題顯示看起來一樣, 但是是用正文加粗和加大字號(hào)來顯示的. 畢竟word是一種文檔格式, 而html是一種標(biāo)記性語言, 要想實(shí)現(xiàn)完美兼容和轉(zhuǎn)換很難

加上word與html互轉(zhuǎn)(2) -- html轉(zhuǎn)word, 雖然word與html互轉(zhuǎn)都有實(shí)現(xiàn)手段, 但是考慮到轉(zhuǎn)換的格式復(fù)雜度和后期的維護(hù)成本, 我們最后放棄去實(shí)現(xiàn)這個(gè)成本高但是對(duì)項(xiàng)目影響不大的功能

其中word轉(zhuǎn)html功能實(shí)現(xiàn)中, 轉(zhuǎn)出的html的格式并沒有想象中的好, 某些樣式是通過class樣式來顯示的, 并不全是行內(nèi)樣式, 并且html所有文本標(biāo)簽都是使用的p標(biāo)簽, 包括標(biāo)題.

實(shí)現(xiàn)

實(shí)現(xiàn)方式

我在網(wǎng)上搜集了很多實(shí)現(xiàn)方式, 各式各樣的, 最后我決定使用poi+xdocreport來實(shí)現(xiàn)
poi都熟悉, 這邊我不作介紹
xdocreport是github上的一個(gè)開源項(xiàng)目, 他的具體介紹可以去他的項(xiàng)目地址查看--項(xiàng)目地址, 選擇這個(gè)開源項(xiàng)目主要有以下幾個(gè)原因:
????1. 他是開源的(免費(fèi))
????2項(xiàng)目本身模塊化, 我們可以只引用需要的功能(輕量化)
????3.轉(zhuǎn)換是基于poi的轉(zhuǎn)換進(jìn)行補(bǔ)充擴(kuò)展的,感覺比poi原生的更好一些(emm...沒驗(yàn)證)
????4.使用簡單便捷
這里只使用了xdocreport的轉(zhuǎn)換器功能, 可以點(diǎn)這里直接查看對(duì)應(yīng)的wiki

引入相關(guān)程序包

 <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轉(zhuǎn)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("這里上傳圖片到圖片服務(wù)器");
                }

                @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();
        }
    }

上面我自己寫的示例跟官方的示例有所區(qū)別, 下面我貼出官方示例然后在進(jìn)行解釋

/**
 * 官方示例
 */
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設(shè)置圖片管理器對(duì)象的時(shí)候
官方是直接設(shè)置了一個(gè)圖片路徑, 生成的html里面的圖片引用指向的是設(shè) 置的路徑, 而我這邊有專門的文件服務(wù)器, 所以需要將里面的圖片上傳到圖片服務(wù)器中, 然后將html中圖片的引用指向文件服務(wù)器, 所以我重寫了圖片管理器的代碼, 將其中保存圖片和給html中圖片引用換成了自己的實(shí)現(xiàn)

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

    @Override
    public void extract(String imagePath, byte[] imageData) throws IOException {
        System.out.println("這里上傳圖片到圖片服務(wù)器");
    }

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

});

2.轉(zhuǎn)換并保存html的時(shí)候
官方示例是將html保存成文件到一個(gè)路徑下面, 而我的需求并不是保存文件, 而是要將生成的html分段下沉到DB, 所以可以在這里

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

將官方示例的文件輸出流換成自己的StringWriter就可以了(你也可以換成自己需要的流), 我這樣替換就可以拿到html的字符串, 接著就可以使用jsoup進(jìn)行html的解析并分段存儲(chǔ)了

doc轉(zhuǎn)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是圖片內(nèi)容, 這里將圖片保存到圖片服務(wù)器, 然后將保存的圖片路徑返回
        //同樣, 你也可以將圖片保存到本地相對(duì)路徑, 然后將相對(duì)路徑返回, html也能正常顯示圖片
        return "https://csdnimg.cn/pubfooter/images/csdn_cs_qr.png";
    });

    wordToHtmlConverter.processDocument(hwpfDocument);

    Transformer transformer = TransformerFactory.newInstance()
                .newTransformer();
    //指定Transformer在輸出結(jié)果樹時(shí)是否可以添加額外的空格
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    //指定輸出編碼
    transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
    transformer.setOutputProperty(OutputKeys.METHOD, "html");

    //這里是希望將轉(zhuǎn)換后的流最終輸出到字符串進(jìn)行返回, 如果你希望直接輸出文件, 你可以創(chuàng)建一個(gè)文件流放進(jìn)下面的參數(shù)
    StringWriter stringWriter = new StringWriter();
    transformer.transform(new DOMSource(wordToHtmlConverter.getDocument()), new StreamResult(stringWriter));

    return stringWriter.toString();
}

示例代碼比較簡單, 但是已經(jīng)具備轉(zhuǎn)換的功能, 需要注意和可能變動(dòng)的點(diǎn)我在代碼注釋中已經(jīng)說明, 可以根據(jù)需求來修改圖片的保存和最后輸出的結(jié)果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子僵娃,更是在濱河造成了極大的恐慌语淘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冤竹,死亡現(xiàn)場離奇詭異财饥,居然都是意外死亡落竹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門剪况,熙熙樓的掌柜王于貴愁眉苦臉地迎上來教沾,“玉大人,你說我怎么就攤上這事译断∈诜” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵孙咪,是天一觀的道長堪唐。 經(jīng)常有香客問我,道長该贾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任捌臊,我火速辦了婚禮杨蛋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘理澎。我一直安慰自己逞力,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布糠爬。 她就那樣靜靜地躺著寇荧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪执隧。 梳的紋絲不亂的頭發(fā)上揩抡,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音镀琉,去河邊找鬼峦嗤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屋摔,可吹牛的內(nèi)容都是我干的烁设。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钓试,長吁一口氣:“原來是場噩夢啊……” “哼装黑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弓熏,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤恋谭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后挽鞠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箕别,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铜幽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了串稀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片除抛。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖母截,靈堂內(nèi)的尸體忽然破棺而出到忽,到底是詐尸還是另有隱情,我是刑警寧澤清寇,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布喘漏,位于F島的核電站,受9級(jí)特大地震影響华烟,放射性物質(zhì)發(fā)生泄漏翩迈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一盔夜、第九天 我趴在偏房一處隱蔽的房頂上張望负饲。 院中可真熱鬧,春花似錦喂链、人聲如沸返十。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洞坑。三九已至,卻和暖如春蝇率,著一層夾襖步出監(jiān)牢的瞬間迟杂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工本慕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逢慌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓间狂,卻偏偏與公主長得像攻泼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鉴象,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 程序設(shè)計(jì)需要將各種需要模擬計(jì)算的內(nèi)容抽象為數(shù)字忙菠。 通常采用二維數(shù)組表示2D地圖 又以不同的數(shù)字代表地圖上不同類型的...
    Godan閱讀 2,069評(píng)論 0 1
  • 博客鏈接:http://www.ideabuffer.cn/2017/05/07/理解CPU-Cache/ CPU...
    閃電是只貓閱讀 3,036評(píng)論 2 14
  • 作為大學(xué)生。對(duì)于我來說纺弊,這是第一個(gè)牛欢,讓我覺得無聊的假期。 怎么說呢淆游,以前放假傍睹,基本上是游戲填充了所有時(shí)光隔盛,并不覺得...
    我懂xxhhz了閱讀 177評(píng)論 0 0
  • 躲在空無一人的樓頂曬太陽,心頭的悲傷都隨著陽光蕩漾拾稳。我嗅出城市的朽爛被蒸發(fā)的味道吮炕,那個(gè)黑暗的影子, 在我的右邊模仿...
    栗子_栗子閱讀 497評(píng)論 4 5
  • 問題嚴(yán)重!中國老齡化調(diào)查報(bào)告 這條音頻給你分享一份悍抑,中國老齡化調(diào)查報(bào)告鳄炉。 大家都知道,中國老齡化的現(xiàn)象是越來越嚴(yán)重...
    嗨嗨皮皮的閱讀 720評(píng)論 0 2