前端實現docx、pdf格式檔案線上預覽

語言: CN / TW / HK

theme: vuepress highlight: atelier-heath-light


介紹

在業務中,如果遇到文件管理類的功能,會出現需要線上預覽的業務需求,本文主要是通過第三方庫來實現文件預覽功能,並將其封裝成preview元件

docx

docx的實現需要使用docx-preview外掛

安裝

npm i docx-preview

使用

建立一個容器標籤 ```html

引入並建立渲染函式js import { renderAsync } from "docx-preview"; renderDocx() { renderAsync(this.fileData, this.$refs.file, null, { className: "docx", //預設和文件樣式類的類名/字首 inWrapper: true, //啟用圍繞文件內容呈現包裝器 ignoreWidth: false, //禁用頁面的渲染寬度 ignoreHeight: false, //禁用頁面的渲染高度 ignoreFonts: false, //禁用字型渲染 breakPages: true, //在分頁符上啟用分頁 ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分頁 experimental: false, //啟用實驗功能(製表符停止計算) trimXmlDeclaration: true, //如果為true,則在解析之前將從xml文件中刪除xml宣告 useBase64URL: false, //如果為true,影象、字型等將轉換為base 64 URL,否則使用URL.createObjectURL useMathMLPolyfill: false, //包括用於鉻、邊等的MathML多填充。 showChanges: false, //啟用文件更改的實驗渲染(插入/刪除) debug: false, //啟用額外的日誌記錄 }); }, ```

PDF

pdf的預覽需要使用PDFJS這個外掛,通過將檔案流解析寫到canvas上實現預覽效果

安裝

npm i pdfjs-dist

引入和使用

```html

此處pdf的渲染資料`this.fileData`必須是一個ArrayBuffer格式的資料,如果請求的的資料是Blob格式必須要先使用`Blob.arrayBuffer()`轉換js async renderPdf(num = 1) { this.fileData.getPage(num).then(page => { // 設定canvas相關的屬性 const canvas = document.getElementById("canvas_" + num); const ctx = canvas.getContext("2d"); const dpr = window.devicePixelRatio || 1; const bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; const ratio = dpr / bsr; const viewport = page.getViewport({ scale: this.pdfScale }); // 設定放縮比率 canvas.width = viewport.width * ratio; canvas.height = viewport.height * ratio; canvas.style.width = viewport.width + "px"; canvas.style.height = viewport.height + "px"; ctx.setTransform(ratio, 0, 0, ratio, 0, 0); const renderContext = { canvasContext: ctx, viewport: viewport, }; // 資料渲染到canvas畫布上 page.render(renderContext); if (this.numPages > num) { setTimeout(() => { return this.renderPdf(num + 1); }); } }); }, ```

pdf的放大和縮小

pdf檔案渲染後如果不能調整大小會因為原始檔的大小和檔案內容,出現模糊的問題,所以進行縮放渲染是有必要的 js // pdf放大 setPdfZoomin() { const max = 2; if (this.pdfScale >= max) { return; } this.pdfScale = this.pdfScale + 0.2; this.renderPdf(); }, // pdf縮小 setPdfZoomout() { const min = 0.6; if (this.pdfScale <= min) { return; } this.pdfScale = this.pdfScale - 0.1; this.renderPdf(); },

多格式的檔案渲染函式對映

因為將多種檔案渲染放在一個檔案中,所以處理函式需要做對映處理,執行對應格式的檔案渲染 js renderPreview(extend) { const handle = { docx: () => { this.extend = "docx"; this.$nextTick(() => this.renderDocx()); }, pdf: () => { this.extend = "pdf"; new Blob([this.fileData]).arrayBuffer().then(res => { PDFJS.getDocument(res).promise.then(pdfDoc => { this.numPages = pdfDoc.numPages; // pdf的總頁數 this.fileData = pdfDoc; this.$nextTick(() => this.renderPdf()); }); }); }, }; this.isLoading = false; if (!Object.hasOwn(handle, extend)) { this.extendName = extend; return (this.extend = "other"); } handle[extend](); },

不支援的檔案提示處理

在這個檔案中,目前只支援docx和pdf的預覽,如果出現了不支援的檔案,需要增加一個提示處理,告知使用者 例如如下的檔案提示 ```html

```

總結

本文只是簡單的總結了關於檔案預覽的純前端實現和封裝方式,對於業務的思路簡單整理,如果是對於有更復雜的場景,還需要有更加具體的拆分和優化。