私有 Word 文件預覽轉 PDF 實現方案

私有 Word 文件在線預覽方案(.doc/.docx 轉 PDF)

前言

由于 .doc.docx Word 文件 無法在瀏覽器中直接預覽(尤其在私有 API 場景下),常見的 Content-Disposition: inline 并不能生效。因此,本方案通過 后端轉換為 PDF 文件,并將其以文檔流形式返回前端,達到可在線閱讀的效果。

效果如圖:
在這里插入圖片描述
在這里插入圖片描述


實現流程概覽

  1. 前端請求文件(非下載模式)
  2. 后端判斷文件擴展名是否為 .doc.docx
  3. 使用 LibreOffice 將 Word 文件轉換為 PDF
  4. 待 PDF 生成后,通過 res.sendFile() 發送給前端
  5. (可選)臨時 PDF 文件使用后自動刪除

實現步驟

🔹 第一步:后端判斷 Word 文件類型并構建 PDF 路徑

const docxRegex = /\.(docx?)$/i; // 支持 .doc 和 .docx(忽略大小寫)if (type !== 'download' && docxRegex.test(filePath)) {const pdfPath = filePath.replace(docxRegex, '.pdf'); // 替換為 PDF 路徑...
}

第二步:安裝 LibreOffice(用于文件轉換)

Ubuntu / Debian:
sudo apt update
sudo apt install libreoffice -y
CentOS / RHEL:
sudo yum install libreoffice -y

第三步:安裝中文字體(避免 PDF 中文亂碼)

推薦使用開源思源字體(Noto 字體家族)

Ubuntu / Debian:
sudo apt install fonts-noto-cjk -y
CentOS / RHEL:
sudo yum install google-noto-sans-cjk-ttc -y

第四步:轉換 Word 文件為 PDF 并返回給前端

const { exec } = require('child_process');
const fs = require('fs');exec(`libreoffice --headless --convert-to pdf "${filePath}" --outdir "${uploadDir}"`, (error, stdout, stderr) => {if (error) {console.error('轉換文件失敗:', error);return res.status(500).json({ message: '轉換文件失敗' });}const waitForPdf = setInterval(() => {if (fs.existsSync(pdfPath) && fs.statSync(pdfPath).size > 1000) {clearInterval(waitForPdf);res.setHeader('Content-Type', 'application/pdf');res.sendFile(pdfPath, (err) => {if (err) {console.error('發送 PDF 文件失敗:', err);return res.status(500).json({ message: '發送失敗' });}// 清理臨時文件fs.unlink(pdfPath, (unlinkErr) => {if (unlinkErr) {console.error('刪除 PDF 失敗:', unlinkErr);} else {console.log('臨時 PDF 已刪除');}});});}}, 100); // 每 100ms 檢查一次 PDF 文件生成狀態
});

補充建議

  • 你可以在服務器上緩存轉換后的 PDF,避免重復轉換
  • 建議加入錯誤重試機制(比如檢測失敗后嘗試轉換 2 次)
  • 如對性能有要求,可使用轉換任務隊列(如 bull.js)

示例:前端預覽

可以獲取

// 查看文檔
async viewDocument(fileData) {let update = { filename: fileData.filename, userId: this.$store.state.userInfo.userId }try {// 設置 responseType 為 'blob' 來正確處理二進制數據const response = await this.$apiRequest('get', '/ser/xxxx', update, '', {responseType: 'blob'});if(response.status === 200) {// 直接使用返回的 blob 數據const blob = response.data;// 創建臨時 URLconst blobUrl = URL.createObjectURL(blob);// 在新窗口中打開文件const newWindow = window.open(blobUrl, '_blank');// 清理臨時 URL(延遲清理,確保文件能正常打開)setTimeout(() => {URL.revokeObjectURL(blobUrl);}, 1000);// 如果無法打開新窗口,提供下載選項if (!newWindow) {this.downloadFile(blob, fileData.name);}}} catch (error) {console.error('查看文檔失敗:', error);this.$message.error('查看文檔失敗,請重試');}
},

備注

注意responseType: 'blob'在接口架構文件里配置一下。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910315.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910315.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910315.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Alpine Docker 容器中安裝包緩存與 C/C++ 運行問題

在使用 Docker 容器部署應用時,基于 Alpine 鏡像能帶來輕量化的優勢,但過程中也會遇到不少問題。今天就來分享下我在 Alpine 容器中解決安裝包緩存與 C/C 程序運行問題的經驗。 一、Alpine 安裝包緩存到本地目錄 Alpine Linux 默認使用apk作為包管理工…

[2-02-02].第59節:功能函數 - 函數基礎

服務器端操作學習大綱 一、函數基礎 需求場景 在shell腳本的編寫過程中,我們經常會遇到一些功能代碼場景:多條命令組合在一起,實現一個特定的功能場景邏輯、一些命令在腳本內部的多個位置頻繁出現。在這些場景的代碼量往往不多,…

RA4M2開發涂鴉模塊CBU(6)----RA4M2驅動涂鴉CBU模組

RA4M2開發涂鴉模塊CBU.6--RA4M2驅動涂鴉CBU模組 概述視頻教學樣品申請參考程序硬件準備接口生成UARTUART屬性配置R_SCI_UART_Open()函數原型回調函數user_uart_callback0 ()變量定義按鍵回調更新按鍵狀態DP-LED 同步長按進入配網涂鴉協議解析主循環任務調度 概述 本方案基于瑞…

MiniMax-M1: Scaling Test-TimeCompute Efficiently with I Lightning Attention

我們推出了MiniMax-M1,這是全球首個開源權重、大規模混合注意力推理模型。MiniMax-M1采用了混合專家系統(Mixture-of-Experts,簡稱MoE)架構,并結合了閃電注意力機制。該模型是在我們之前的MiniMax-Text-01模型&#xf…

Appium+python自動化(二十六) -Toast提示

在日常使用App過程中,經常會看到App界面有一些彈窗提示(如下圖所示)這些提示元素出現后等待3秒左右就會自動消失,那么我們該如何獲取這些元素文字內容呢? Toast簡介 Android中的Toast是一種簡易的消息提示框。 當視圖…

【信號與系統三】離散時間傅里葉變換

上一講我們講述了連續時間傅里葉變換,這一講同理來個離散時間傅里葉變換。 和上講模塊類似 5.1離散時間傅里葉變換 這一式子就是離散時間傅里葉變換對 5.2周期信號的傅里葉變換 同理,由于之前第一講講到: 可以推出: 舉個例子&am…

Python應用石頭剪刀布練習初解

大家好!作為 Python 初學者,尋找一個既簡單又有趣的項目來練習編程技能是至關重要的。今天,我將向大家介紹一個經典的編程練習——石頭剪刀布游戲,它可以幫助你掌握 Python 的基本概念,如條件語句、隨機數生成和用戶輸入處理等。 …

私有規則庫:企業合規與安全的終極防線

2.1 為什么企業需要私有規則庫?——合規與安全的最后防線 真實案例:2023年某跨境電商因員工泄露內部檢測規則,導致黑產繞過風控系統,損失1200萬+ 企業規則庫的三大剛需: 行業合規: 金融行業需符合《個人金融信息保護技術規范》 醫療行業需滿足HIPAA患者數據脫敏要求 業…

長尾關鍵詞優化SEO核心策略

內容概要 本文旨在系統解析長尾關鍵詞在搜索引擎優化中的核心地位,為讀者提供從理論到實踐的全面指南。文章首先探討長尾關鍵詞的基礎作用,幫助理解其在提升網站流量質量中的價值。接著,深入介紹精準定位低搜索量、高轉化率關鍵詞的策略&…

騰訊云事件總線:構建毫秒級響應的下一代事件驅動架構

摘要 事件總線(EventBridge)作為云原生架構的核心樞紐,其性能與可靠性直接影響企業系統彈性。騰訊云事件總線基于TGW云網關底層能力重構,實現單節點吞吐量提升125%、故障恢復時間降至4秒級(行業平均>30秒&#xff0…

PyTorch 中mm和bmm函數的使用詳解

torch.mm 是 PyTorch 中用于 二維矩陣乘法(matrix-matrix multiplication) 的函數,等價于數學中的 A B 矩陣乘積。 一、函數定義 torch.mm(input, mat2) → Tensor執行的是兩個 2D Tensor(矩陣)的標準矩陣乘法。 in…

Qt 解析復雜對象構成

Qt 解析復雜對象構成 dumpStructure 如 QComboBox / QCalendarWidget / QSpinBox … void Widget::Widget(QWidget* parent){auto c new QCalendarWidget(this);dumpStructure(c,4); }void Widget::dumpStructure(const QObject *obj, int spaces) {qDebug() << QString…

山姆·奧特曼:從YC到OpenAI,硅谷創新之星的崛起

名人說&#xff1a;路漫漫其修遠兮&#xff0c;吾將上下而求索。—— 屈原《離騷》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 山姆奧特曼&#xff1a;從YC到OpenAI&#xff0c;硅谷創新之星的崛起 在人工智能革命…

PHP語法基礎篇(五):流程控制

任何 PHP 腳本都是由一系列語句構成的。一條語句可以是一個賦值語句&#xff0c;一個函數調用&#xff0c;一個循環&#xff0c;一個條件語句或者甚至是一個什么也不做的語句&#xff08;空語句&#xff09;。語句通常以分號結束。此外&#xff0c;還可以用花括號將一組語句封裝…

怎么隱藏關閉或恢復顯示輸入法的懸浮窗

以搜狗輸入法為例&#xff0c;隱藏輸入法懸浮窗 懸浮窗在輸入法里的官方叫法為【狀態欄】。 假設目前大家的輸入法相關顯示呈現如下狀態&#xff1a; 那我們只需在輸入法懸浮窗&#xff08;狀態欄&#xff09;的任意位置鼠標右鍵單擊&#xff0c;調出輸入法菜單&#xff0c;就…

Electron (02)集成 SpringBoot:服務與桌面程序協同啟動方案

本篇是關于把springboot生成的jar打到electron里&#xff0c;在生成的桌面程序啟動時springboot服務就會自動啟動。 雖然之后并不需要這種方案&#xff0c;更好的是部署[一套服務端&#xff0c;多個客戶端]...但是既然搭建成功了&#xff0c;也記錄一下。 前端文件 1、main.js…

2025年計算機應用與神經網絡國際會議(CANN 2025)

2025 International Conference on Computer Applications and Neural Networks &#xff08;一&#xff09;會議信息 會議簡稱&#xff1a;CANN 2025 大會地點&#xff1a;中國重慶 收錄檢索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Scholar等 &#xff08;二&#x…

振動分析中的低頻噪聲問題:從理論到實踐的完整解決方案

前言 在振動監測和結構健康監測領域&#xff0c;我們經常需要從加速度信號計算速度和位移。然而&#xff0c;許多工程師在實際應用中都會遇到一個令人困擾的問題&#xff1a;通過積分計算得到的速度和位移頻譜中低頻噪聲異常放大。 本文將深入分析這個問題的根本原因&#xf…

ncu學習筆記01——合并訪存

全局內存通過緩存實現加載和存儲過程。其中&#xff0c;L1為一級緩存&#xff0c;每個SM都有自己的L1&#xff1b;L2為二級緩存&#xff0c;L2則被所有SM共有。 數據從全局內存到SM的傳輸過程中&#xff0c;會去L1和L2中查詢是否有緩存。對全局內存的訪問將經過L1&#xff1b;…

2012 - 正方形矩陣

????題目描述 晶晶同學非常喜歡方形&#xff0c;她希望打印出來的字符串也是方形的。老師給了晶晶同學一個字符串"ACM"&#xff0c;晶晶同學突發奇想&#xff0c;如果任意給定義一個整數n&#xff0c;能不能打印出由這個字符串組成的正方形字符串呢&#xff1f;…