如何将Docxtemplater生成的DOCX文档在页面转换为PDF?
将生成的DOCX文档转换为PDF的方案
问题背景
我制作了一个生成Word DOCX文档的页面,当前使用以下代码生成DOCX文档:
function loadFile(url,callback){ PizZipUtils.getBinaryContent(url,callback); } function gen(id, dane) { $.ajax({ url:"create.php", method:"post", data:{id}, success:function(data) { dane.numer = data; generate(dane); } }); } function generate(data) { loadFile("/doc.docx",function(error,content){ if (error) { throw error }; function replaceErrors(key, value) { if (value instanceof Error) { return Object.getOwnPropertyNames(value).reduce(function(error, key) { error[key] = value[key]; return error; }, {}); } return value; } function errorHandler(error) { console.log(JSON.stringify({error: error}, replaceErrors)); if (error.properties && error.properties.errors instanceof Array) { const errorMessages = error.properties.errors.map(function (error) { return error.properties.explanation; }).join("\n"); console.log('errorMessages', errorMessages); } throw error; } var zip = new PizZip(content); var doc; try { doc=new window.docxtemplater(zip); } catch(error) { errorHandler(error); } doc.setData(data); try { doc.render(); } catch (error) { errorHandler(error); } var out=doc.getZip().generate({ type:"blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }) saveAs(out,"Prot "+ data.name +".docx") }) }
请问如何在该页面将生成的Word DOCX文档转换为PDF文件?
解决方案
方案一:前端纯JS转换(适合简单文档)
这种方式无需后端参与,但对复杂样式(如表格、特殊字体、分页)支持有限。
- 引入依赖库
通过CDN引入处理DOCX转HTML、HTML转PDF的工具:
<script src="https://unpkg.com/mammoth@1.6.0/mammoth.browser.min.js"></script> <script src="https://unpkg.com/jspdf@2.5.1/dist/jspdf.umd.min.js"></script> <script src="https://unpkg.com/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
- 修改生成逻辑,添加转换代码
在原generate函数生成DOCX Blob后,新增转换逻辑:
function generate(data) { loadFile("/doc.docx",function(error,content){ // 原DOCX生成代码保持不变 var out=doc.getZip().generate({ type:"blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); // 新增:DOCX转PDF逻辑 convertDocxToPdf(out, data.name); // 可选:保留原DOCX下载 saveAs(out,"Prot "+ data.name +".docx"); }) } // 定义转换函数 function convertDocxToPdf(docxBlob, filename) { const reader = new FileReader(); reader.onload = function(e) { // 将DOCX转为HTML mammoth.convertToHtml({arrayBuffer: e.target.result}) .then(result => { const html = result.value; // 处理转换提示(可选) result.messages.forEach(msg => console.log(`${msg.type}: ${msg.message}`)); // 将HTML转为PDF const { jsPDF } = window.jspdf; const pdfDoc = new jsPDF('p', 'mm', 'a4'); // 用html2canvas处理HTML后生成PDF(适配复杂元素) const tempContainer = document.createElement('div'); tempContainer.style.display = 'none'; tempContainer.innerHTML = html; document.body.appendChild(tempContainer); html2canvas(tempContainer) .then(canvas => { const imgData = canvas.toDataURL('image/png'); const imgWidth = 210; const pageHeight = 297; const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; pdfDoc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; // 处理分页 while (heightLeft >= 0) { position = heightLeft - imgHeight; pdfDoc.addPage(); pdfDoc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } // 下载PDF pdfDoc.save(`Prot ${filename}.pdf`); document.body.removeChild(tempContainer); }); }) .catch(err => console.error('DOCX转HTML失败:', err)); }; reader.readAsArrayBuffer(docxBlob); }
方案二:后端转换(推荐,样式还原度高)
通过后端服务处理转换,适合复杂文档,样式还原更准确。
- 前端修改:上传DOCX到后端
function generate(data) { loadFile("/doc.docx",function(error,content){ // 原DOCX生成代码保持不变 var out=doc.getZip().generate({ type:"blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); // 上传DOCX到后端转换 const formData = new FormData(); formData.append('docxFile', out, 'temp.docx'); formData.append('filename', data.name); $.ajax({ url: 'convert_to_pdf.php', method: 'POST', data: formData, processData: false, contentType: false, success: function(pdfData) { const blob = new Blob([pdfData], {type: 'application/pdf'}); saveAs(blob, `Prot ${data.name}.pdf`); }, error: xhr => console.error('转换失败:', xhr.responseText) }); // 可选:保留原DOCX下载 saveAs(out,"Prot "+ data.name +".docx"); }) }
- 后端PHP示例(基于LibreOffice命令行,效率高)
确保服务器已安装LibreOffice,创建convert_to_pdf.php:
<?php if ($_FILES['docxFile']['error'] === UPLOAD_ERR_OK) { $inputPath = $_FILES['docxFile']['tmp_name']; $outputDir = sys_get_temp_dir(); $outputPath = tempnam($outputDir, 'pdf_') . '.pdf'; $filename = $_POST['filename']; // 调用LibreOffice命令转换 $command = "libreoffice --headless --convert-to pdf --outdir " . escapeshellarg($outputDir) . " " . escapeshellarg($inputPath); exec($command, $outputLogs, $returnCode); if ($returnCode === 0 && file_exists($outputPath)) { header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="Prot ' . $filename . '.pdf"'); readfile($outputPath); unlink($outputPath); } else { http_response_code(500); echo "转换失败: " . implode("\n", $outputLogs); } } else { http_response_code(400); echo "文件上传失败"; } ?>
注意事项
- 前端转换仅适合结构简单的文档,复杂样式优先选择后端方案
- 后端使用LibreOffice时,需确保服务器已安装该软件,且命令行执行权限正常
- 转换大文件时,需调整服务器的上传大小和超时限制
内容的提问来源于stack exchange,提问作者miko
相关产品推荐
相关产品推荐

