如何在Angular 15中使用docxjs将生成的docx转为PDF?
问题分析
直接修改Blob的MIME类型只是修改了文件的标识,并没有真正将docx的内容转换为PDF格式——docx和PDF是结构完全不同的文档格式,必须通过专门的格式转换工具处理,所以直接改类型的文件无法正常打开。
以下是两种可行的转换方案:
方案一:前端直接转换(适合简单文档)
通过两个库配合完成转换:mammoth.js(将docx解析为HTML) + html2pdf.js(将HTML转为PDF)
步骤:
- 安装依赖:
npm install mammoth html2pdf.js
- 修改下载函数:
import * as mammoth from 'mammoth'; import html2pdf from 'html2pdf.js'; public download(data: any): void { const documentCreator = new DocumentCreator(); const doc = documentCreator.create(data); const filename = `Contrato ${data.place} ${_moment(data.dateEvent).format('LL')}`; Packer.toBlob(doc).then(async (docxBlob) => { // 1. 将docx Blob转为ArrayBuffer,用mammoth解析成HTML const arrayBuffer = await docxBlob.arrayBuffer(); const parseResult = await mammoth.convertToHtml({ arrayBuffer }); const htmlContent = parseResult.value; // 2. 用html2pdf将HTML转为PDF并下载 const convertOptions = { margin: 1, filename: `${filename}.pdf`, image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2 }, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } }; html2pdf().set(convertOptions).from(htmlContent).save(); this.closeModalExport(); }); }
注意:该方案对复杂docx(如包含复杂表格、特殊样式、嵌入式图片)的支持有限,可能出现样式丢失问题。
方案二:后端转换(推荐,支持复杂文档)
前端将生成的docx Blob发送到后端,后端用专业工具转换为PDF后返回给前端下载,这种方式能更好保留文档样式和复杂内容。
后端示例(Node.js)
依赖libreoffice-convert库(需先在服务器安装LibreOffice):
const express = require('express'); const multer = require('multer'); const libre = require('libreoffice-convert'); const app = express(); const upload = multer({ storage: multer.memoryStorage() }); app.post('/convert-to-pdf', upload.single('docx'), (req, res) => { const docxBuffer = req.file.buffer; libre.convert(docxBuffer, '.pdf', undefined, (err, pdfBuffer) => { if (err) { return res.status(500).send('PDF转换失败'); } res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename=${req.body.filename}`); res.send(pdfBuffer); }); }); app.listen(3000);
前端修改:
public download(data: any): void { const documentCreator = new DocumentCreator(); const doc = documentCreator.create(data); const filename = `Contrato ${data.place} ${_moment(data.dateEvent).format('LL')}`; Packer.toBlob(doc).then(async (docxBlob) => { const formData = new FormData(); formData.append('docx', docxBlob, `${filename}.docx`); formData.append('filename', `${filename}.pdf`); const response = await fetch('/convert-to-pdf', { method: 'POST', body: formData }); const pdfBlob = await response.blob(); saveAs(pdfBlob, `${filename}.pdf`); this.closeModalExport(); }); }
内容的提问来源于stack exchange,提问作者André Ibarra
相关产品推荐
相关产品推荐

