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)頁(yè)或電子郵件中的文本和圖形。相比于寫字板和記事本功能更強(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ǎn)單總結(jié)兩者區(qū)別:
- docx和doc相比文件體積更小,對(duì)復(fù)雜對(duì)象的處理也更好
- 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)容渲染出來或傳遞給后端
兩種方案,說不上誰(shuí)好誰(shuí)壞,只有視業(yè)務(wù)場(chǎng)景來決定。
本文僅分享方案二的實(shí)現(xiàn)。想了解后端解析請(qǐng)移步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的目的。
前提是對(duì)XML標(biāo)簽熟悉,總不能瞎轉(zhuǎn)吧?。?!
不用擔(dān)心,不熟悉也沒關(guān)系,我們站在前人的肩膀上做這一步。
Mammoth是什么
Mammoth是一個(gè)專注于轉(zhuǎn)換 .docx 文檔的工具庫(kù),它能將Microsoft Word、Google Docs 和 LibreOffice 創(chuàng)建的文檔轉(zhuǎn)換成HTML,Mammoth會(huì)利用文檔的XML語(yǔ)義信息,忽略其他細(xì)節(jié),從而生成簡(jiǎn)單明了的 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,又能摸魚了。
更高級(jí)的摸魚
平常的學(xué)習(xí)、工作中,經(jīng)常性出現(xiàn)某個(gè)項(xiàng)目開發(fā)上線某個(gè)功能,另外一個(gè)項(xiàng)目也提出相同的功能需求。歷史總是驚人的相似。
為了以后再遇到類似需求,我把docx文件轉(zhuǎn)換HTML這段代碼保存在CodeGist中,方便下次直接引用。
CodeGist是一款代碼管理工具,詳細(xì)介紹請(qǐng)移步【工具推薦】代碼管理工具 CodeGist
以上就是JavaScript實(shí)現(xiàn)將Word文檔解析成瀏覽器認(rèn)識(shí)的HTML的詳細(xì)內(nèi)容,更多關(guān)于JavaScript Word解析成HTML的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
json 帶斜杠時(shí)如何解析的實(shí)現(xiàn)
這篇文章主要介紹了json 帶斜杠時(shí)如何解析的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Electron 使? 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-10Bootstrap Tree View簡(jiǎn)單而優(yōu)雅的樹結(jié)構(gòu)組件實(shí)例解析
本文通過實(shí)例代碼給大家介紹了Bootstrap Tree View簡(jiǎn)單而優(yōu)雅的樹結(jié)構(gòu)組件,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06JavaScript檢測(cè)彈出窗口是否已經(jīng)關(guān)閉的方法
這篇文章主要介紹了JavaScript檢測(cè)彈出窗口是否已經(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組件簡(jiǎn)單用法示例【附demo源碼下載】
這篇文章主要介紹了微信小程序picker組件簡(jiǎn)單用法,結(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-10JavaScript原型鏈與繼承操作實(shí)例總結(jié)
這篇文章主要介紹了JavaScript原型鏈與繼承操作,結(jié)合實(shí)例形式總結(jié)分析了javascript原形鏈與繼承的相關(guān)概念、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2018-08-08