私有 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 路径

js 复制代码
const docxRegex = /\.(docx?)$/i; // 支持 .doc 和 .docx(忽略大小写)

if (type !== 'download' && docxRegex.test(filePath)) {
  const pdfPath = filePath.replace(docxRegex, '.pdf'); // 替换为 PDF 路径
  ...
}

第二步:安装 LibreOffice(用于文件转换)

Ubuntu / Debian:
bash 复制代码
sudo apt update
sudo apt install libreoffice -y
CentOS / RHEL:
bash 复制代码
sudo yum install libreoffice -y

第三步:安装中文字体(避免 PDF 中文乱码)

推荐使用开源思源字体(Noto 字体家族)

Ubuntu / Debian:
bash 复制代码
sudo apt install fonts-noto-cjk -y
CentOS / RHEL:
bash 复制代码
sudo yum install google-noto-sans-cjk-ttc -y

第四步:转换 Word 文件为 PDF 并返回给前端

js 复制代码
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)

示例:前端预览

可以获取

html 复制代码
// 查看文档
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;
      
      // 创建临时 URL
      const 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'在接口架构文件里配置一下。

相关推荐
2601_9618752417 小时前
高考真题电子版|2025高考全科真题分类PDF
金融·pdf·云计算·azure·七牛云存储·交友·高考
质造者18 小时前
Python 本地 RAG 实战 | Ollama+ChromaDB 实现 PDF 离线智能问答
开发语言·python·pdf·大模型·rag
王莎莎-MinerU18 小时前
从 OCR 到 Context Engineering:用 MinerU 搭一个可复现文档解析评测
人工智能·深度学习·机器学习·pdf·ocr·个人开发
DS随心转小程序20 小时前
AI导出鸭 从 Markdown 草稿到精品 Word 文档的无损之道
人工智能·word·豆包·deepseek·ai导出鸭
asdzx6720 小时前
使用 C# 轻松为 Word 文档添加数字签名
c#·word
m0_5474866620 小时前
华南农业大学《数据结构》期末试卷及答案2011-2019 2020-2023年PDF
大数据·数据结构·pdf·华南农业大学
ComPDFKit21 小时前
2026 PDF 表格提取工具横评:15 款工具实测对比
pdf·excel·pdf表格提取·pdf to excel·pdf数据提取
百事牛科技21 小时前
Word只打需要的部分:4种打印范围设置方法
windows·word
m0_5474866621 小时前
华南农业大学《C语言程序设计》期末试卷及答案2018-2025年PDF
c语言·开发语言·pdf·c语言程序设计
Metaphor6922 天前
使用 Python 给 PDF 设置背景色或背景图
数据库·python·pdf