JavaScript實(shí)現(xiàn)將Word文檔解析成瀏覽器認(rèn)識(shí)的HTML
前言
領(lǐng)導(dǎo)跟富文本編輯器杠上啦,領(lǐng)導(dǎo)有一個(gè)類似于某雀導(dǎo)入Word文檔,解析內(nèi)容后渲染到編輯器編輯的需求。某雀功能效果如下:

怎么搞定呢?自己寫一個(gè)解析器?
本文分享Word文件轉(zhuǎn)換成瀏覽器認(rèn)識(shí)的HTML實(shí)戰(zhàn)經(jīng)驗(yàn)。
什么是Word文檔
Word是微軟公司開發(fā)的一個(gè)文字處理器應(yīng)用程序,它是Office軟件中的一個(gè)組件。使用Microsoft Office Word可創(chuàng)建和編輯信件、報(bào)告、網(wǎng)頁或電子郵件中的文本和圖形。相比于寫字板和記事本功能更強(qiáng)大,性能更全面,可以插入圖片、多媒體、藝術(shù)效果等
Word 支持的文件格式
列舉一下Word常用的幾種文件模式:

Word支持的文檔格式蠻多,想了解的讀者移步Word、Excel 和 PowerPoint 的文件格式參考。
docx、doc有什么區(qū)別
Word文檔格式相信讀者跟我一樣見過最多的是docx、doc格式。
有了doc為啥又帶出個(gè)docx?
網(wǎng)上流傳一個(gè)故事:從某一時(shí)期開始微軟辦公文件名的小尾巴多了一個(gè)“x”。原來word、PowerPoint還有excel,后綴名分別是doc、ppt、xls。后來,就突然涌現(xiàn)出了docx、pptx、xlsx。
原來的doc格式是加密的,只有微軟自己家的軟件才能打開。
后來微軟覺得,這樣并沒有讓自己很神圣,反而限制了自己的發(fā)展。
比如,金山WPS也是搞辦公軟件的,它的發(fā)展很快,積累了很多用戶。不少人開始用wps了,word的用戶面臨被瓜分。于是,微軟就基于Office Open XML標(biāo)準(zhǔn),把文檔家族做了兼容。
因?yàn)樾聵?biāo)準(zhǔn)是采用的xml格式記錄信息的,所以就在.doc后面加了個(gè)x。新標(biāo)準(zhǔn)之后,即便是微軟創(chuàng)建的文檔,WPS也能打開。這樣,用戶只關(guān)心文檔就行,不用在意用哪個(gè)軟件,這就實(shí)現(xiàn)了用戶共享。
當(dāng)然我不能驗(yàn)證是否是真的,聽說而已。
簡單總結(jié)兩者區(qū)別:
- docx和doc相比文件體積更小,對復(fù)雜對象的處理也更好
- docx是為了替代doc:Microsoft Word 2007版本開始,docx已經(jīng)替代了doc,doc也不再進(jìn)行開發(fā)
- doc是二進(jìn)制文件,docx是xml文件。docx擴(kuò)展名可修改為zip、rar等壓縮包格式,使用壓縮軟件打開,查看內(nèi)部各類文件,實(shí)現(xiàn)批量替換圖片等
Word文檔轉(zhuǎn)HTML實(shí)戰(zhàn)
市面上實(shí)現(xiàn)該功能方案有兩種:
- 前端把Word文檔上傳給后端,由后端來解析,然后在通過接口把解析的內(nèi)容返回給前端
- 前端解析,直接把解析后的內(nèi)容渲染出來或傳遞給后端
兩種方案,說不上誰好誰壞,只有視業(yè)務(wù)場景來決定。
本文僅分享方案二的實(shí)現(xiàn)。想了解后端解析請移步Word轉(zhuǎn)換HTML(Java實(shí)用版)。
怎么來解析
docx看起來是一個(gè)文件,其實(shí)是一個(gè)壓縮包,它的文件結(jié)構(gòu)是這樣的:

位于word下的document.xml文件docx的主文件??梢哉f,文檔中你能看到的所有內(nèi)容,在這里都有直接或者間接的記錄。
document.xml內(nèi)容都被XML標(biāo)簽進(jìn)行了包裹,把XML標(biāo)簽轉(zhuǎn)化成HTML標(biāo)簽即達(dá)成Word轉(zhuǎn)HTML的目的。
前提是對XML標(biāo)簽熟悉,總不能瞎轉(zhuǎn)吧?。?!
不用擔(dān)心,不熟悉也沒關(guān)系,我們站在前人的肩膀上做這一步。
Mammoth是什么
Mammoth是一個(gè)專注于轉(zhuǎn)換 .docx 文檔的工具庫,它能將Microsoft Word、Google Docs 和 LibreOffice 創(chuàng)建的文檔轉(zhuǎn)換成HTML,Mammoth會(huì)利用文檔的XML語義信息,忽略其他細(xì)節(jié),從而生成簡單明了的 HTML。比如Mammoth會(huì)將任何帶有標(biāo)題 1 樣式的段落轉(zhuǎn)換為 h1 元素,但不會(huì)把標(biāo)題的樣式(字體、文字大小、顏色等)全部復(fù)制過去。
Mammoth支持以下功能:
- 標(biāo)題
- 列表
- 標(biāo)題
- 列表
- 可定制的 docx 樣式到 HTML 的映射。例如,您可以通過提供適當(dāng)?shù)臉邮接成?,?WarningHeading 轉(zhuǎn)換為 h1.warning
- 表格:表格格式(如邊框)會(huì)被忽略
- 腳注和尾注
- 圖片
- 粗體、斜體、下劃線、刪除線、上標(biāo)和下標(biāo)。
- 鏈接
- 換行
- 文本框:文本框的內(nèi)容被視為一個(gè)單獨(dú)的段落,出現(xiàn)在包含文本框的段落之后。
- 注釋
Mammoth提供了支持將docx轉(zhuǎn)換成Markdown、HTML、純文本的方法。
Mammoth實(shí)戰(zhàn)
Mammoth官方demo:
const mammoth = require("mammoth");
mammoth.convertToHtml({path: "path/to/document.docx"})
.then(function(result){
const html = result.value; // 轉(zhuǎn)換的HTML
const messages = result.messages;
})
.catch(function(error) {
console.error(error);
});
這是在Node.js環(huán)境中的案例,瀏覽器環(huán)境是無法通過{path: "path/to/document.docx"}來讀取到docx文件。
如果是要在瀏覽器環(huán)境中執(zhí)行它,需要docx文件轉(zhuǎn)化為arrayBuffer數(shù)組再作為參數(shù)傳遞給convertToHtml:
const updateWord = {
handleFileSelect(event) {
const self = this
this.readFileInputEventAsArrayBuffer(event, function (arrayBuffer) {
mammoth.convertToHtml({ arrayBuffer: arrayBuffer }, {
//...
})
}
},
//文件轉(zhuǎn)化成arrayBuffer數(shù)據(jù)類型
readFileInputEventAsArrayBuffer(event, callback) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function (loadEvent) {
const arrayBuffer = loadEvent.target.result;
callback(arrayBuffer);
};
reader.readAsArrayBuffer(file);
}
}
//獲取文件file后,傳遞給handleFileSelect函數(shù)
updateWord.handleFileSelect(file)
Word文檔也許存在圖片,Mammoth默認(rèn)會(huì)把圖片轉(zhuǎn)成base64格式,這樣我們得到的HTML內(nèi)容會(huì)特殊的大。正常情況我們肯定是想要把圖片上傳到我們自己的服務(wù)器,HTML內(nèi)容保留圖片鏈接即可。
Mammoth也提供了相應(yīng)方法:
const updateWord = {
//base64格式轉(zhuǎn)blob
base64ToBlob(base64, mimeType) {
let bytes = window.atob(base64);
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ia], { type: mimeType });
},
handleFileSelect(event,{success, fail}) {
const self = this
this.readFileInputEventAsArrayBuffer(event, function (arrayBuffer) {
mammoth.convertToHtml({ arrayBuffer: arrayBuffer }, {
//處理圖片
convertImage: mammoth.images.imgElement(function (image) {
return image.read("base64").then(async (imageBuffer) => {
//base64轉(zhuǎn)blob
const blob = self.base64ToBlob(imageBuffer, 'image/png')
blob.name = Date.now() + '.png'
const result = await new Promise((resolve, reject) => {
//圖片上傳邏輯,可以自定義
upImage({ file: blob }, {
resolve,
reject
})
})
const url = result.default
return {
src: url
}
});
})
}).then(success, fail);
}
},
//...
}
upImage是上傳圖片到我們自己服務(wù)器的邏輯,這個(gè)邏輯大家自定義發(fā)揮,只要最后把圖片鏈接返回return {src: url},它會(huì)把base64替換掉。
至此,完成Word文檔轉(zhuǎn)換HTML,又能摸魚了。
更高級的摸魚
平常的學(xué)習(xí)、工作中,經(jīng)常性出現(xiàn)某個(gè)項(xiàng)目開發(fā)上線某個(gè)功能,另外一個(gè)項(xiàng)目也提出相同的功能需求。歷史總是驚人的相似。
為了以后再遇到類似需求,我把docx文件轉(zhuǎn)換HTML這段代碼保存在CodeGist中,方便下次直接引用。

CodeGist是一款代碼管理工具,詳細(xì)介紹請移步【工具推薦】代碼管理工具 CodeGist
以上就是JavaScript實(shí)現(xiàn)將Word文檔解析成瀏覽器認(rèn)識(shí)的HTML的詳細(xì)內(nèi)容,更多關(guān)于JavaScript Word解析成HTML的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
json 帶斜杠時(shí)如何解析的實(shí)現(xiàn)
這篇文章主要介紹了json 帶斜杠時(shí)如何解析的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Electron 使? electron-builder 打包應(yīng)用過程詳解
Electron應(yīng)用開發(fā)中,electron-builder是一個(gè)常用的打包工具,提供了多種自定義配置,不過,使用npm安裝electron-builder時(shí)可能會(huì)遇到下載依賴慢或失敗的問題,本文給大家介紹Electron 使? electron-builder 打包應(yīng)用的相關(guān)操作,感興趣的朋友一起看看吧2024-10-10
Bootstrap Tree View簡單而優(yōu)雅的樹結(jié)構(gòu)組件實(shí)例解析
本文通過實(shí)例代碼給大家介紹了Bootstrap Tree View簡單而優(yōu)雅的樹結(jié)構(gòu)組件,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06
JavaScript檢測彈出窗口是否已經(jīng)關(guān)閉的方法
這篇文章主要介紹了JavaScript檢測彈出窗口是否已經(jīng)關(guān)閉的方法,涉及javascript中window屬性的closed屬性的使用技巧,需要的朋友可以參考下2015-03-03
判斷是否存在子節(jié)點(diǎn)的實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄袛嗍欠翊嬖谧庸?jié)點(diǎn)的實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05
微信小程序picker組件簡單用法示例【附demo源碼下載】
這篇文章主要介紹了微信小程序picker組件簡單用法,結(jié)合實(shí)例形式詳細(xì)分析了picker組件的功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-12-12
原生js和jQuery隨意改變div屬性style的名稱和值
用原生js和jQuery實(shí)現(xiàn)改變隨意改變div屬性style的名稱和值的結(jié)果,這個(gè)實(shí)例比較實(shí)用,新手朋友們可以看看2014-10-10
JavaScript原型鏈與繼承操作實(shí)例總結(jié)
這篇文章主要介紹了JavaScript原型鏈與繼承操作,結(jié)合實(shí)例形式總結(jié)分析了javascript原形鏈與繼承的相關(guān)概念、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2018-08-08

