LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【WEB开发】HTML 实现 PDF 下载功能完整指南

admin
2025年7月3日 7:52 本文热度 79

在网页开发中,实现 PDF 下载功能是常见的需求。以下是几种主流实现方式及其详细代码示例: 

方案一,使用浏览器原生API(window.print)

<!DOCTYPE html><html><head>    <title>打印为PDF</title>    <style>        @media print {            .no-print {                display: none;            }            body {                margin0;                padding10mm;            }        }    </style></head><body>    <div id="printable-content">        <h1>可打印内容</h1>        <p>使用浏览器打印功能保存为PDF</p>    </div>
    <button class="no-print" onclick="window.print()">打印/保存为PDF</button></body></html>

这个插件仅仅是唤起打印的功能,让用户另存为 pdf 不合适

方案二,使用纯前端方案(jsPDF + html2canvas)

<!DOCTYPE html><html><head>    <title>HTML转PDF</title>    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>    <style>        #content {            width800px;            padding20px;            background#f5f5f5;        }    </style></head><body>    <div id="content">        <h1>这是要导出为PDF的内容</h1>        <p>使用jsPDF和html2canvas库可以轻松实现HTML转PDF功能</p>        <table border="1">            <tr><th>姓名</th><th>年龄</th></tr>            <tr><td>张三</td><td>25</td></tr>        </table>    </div>
    <button onclick="generatePDF()">下载PDF</button>
    <script>        function generatePDF() {            const { jsPDF } = window.jspdf;            const element = document.getElementById('content');
            html2canvas(element).then(canvas => {                const imgData = canvas.toDataURL('image/png');                const pdf = new jsPDF('p''mm''a4');                const imgProps = pdf.getImageProperties(imgData);                const pdfWidth = pdf.internal.pageSize.getWidth();                const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
                pdf.addImage(imgData, 'PNG'00, pdfWidth, pdfHeight);                pdf.save('document.pdf');            });        }    </script></body></html>

看着几乎完美,这个技术栈,最核心的就是:必须要用到 dom 元素渲染,试想一下,你做了一个导出功能,总不能让客户必须先打开页面等 html 渲染完后,再导出吧?或者display:none,打印出来一个空白。

此路不通,就只能重新寻找新的方向

方案三,html2pdf

npm install html2pdf.js

<template>  <div class="container">    <button @click="generatePDF">下载PDF</button>  </div></template><script setup>import html2pdf from 'html2pdf.js'// 使用示例let element = `    <h1>前端人</h1>    <p>学好前端,走遍天下都不怕</p>    ...`;function generatePDF() {    // 配置选项    const opt = {      margin:       10,      filename:     'hello_world.pdf',      image:        { type'jpeg'quality0.98 },      html2canvas:  { scale2 },      jsPDF:        { unit'mm'format'a4'orientation'portrait' }    };    // 生成PDF并导出    html2pdf().from(element).set(opt).save();}</script>

功能正常,似乎一切都完美

问题没有想的那么简单如果我们的html是纯文本元素,这程序跑起来没有任何问题,但我们抓取的信息都源于互联网,html结构怎么可能会这么简单?如果我们的html中包含图片信息 ,此时你会发现,导出来的 pdf,图片占位处是个空白块

那我理解的图片同步加载是什么意思呢?简单来说,就是将图片转成Base64,因为这种方式,即使说无网的情况也能正常加载图片,因此我凭感觉断定,这就是图片同步加载

基于这个思路,我写了个完整 demo

<template>  <div class="container">    <button @click="generatePDF">下载PDF</button>  </div></template><script setup>import html2pdf from 'html2pdf.js'async function convertImagesToBase64(htmlString) {  // 创建一个临时DOM元素来解析HTML  const tempDiv = document.createElement('div');  tempDiv.innerHTML = htmlString;  // 获取所有图片元素  const images = tempDiv.querySelectorAll('img');  // 遍历每个图片并转换  for (const img of images) {    try {      const base64 = await getBase64FromUrl(img.src);      img.src = base64;    } catch (error) {      console.error(`无法转换图片 ${img.src}:`, error);      // 保留原始URL如果转换失败    }  }  // 返回转换后的HTML  return tempDiv.innerHTML;}// 图片转base64function getBase64FromUrl(url) {  return new Promise((resolve, reject) => {    const img = new Image();    img.crossOrigin = 'Anonymous'// 处理跨域问题    img.onload = () => {      const canvas = document.createElement('canvas');      canvas.width = img.width;      canvas.height = img.height;      const ctx = canvas.getContext('2d');      ctx.drawImage(img, 00);      // 获取Base64数据      const dataURL = canvas.toDataURL('image/png');      resolve(dataURL);    };    img.onerror = () => {      reject(new Error('图片加载失败'));    };    img.src = url;  });}// 使用示例let element = `  <div>    <img src='http://t13.baidu.com/it/u=2041049195,1001882902&fm=224&app=112&f=JPEG?w=500&h=500' style="width: 300px;" />    <p>职业:前端</p>    <p>技能:唱、跳、rap</p>  </div>`;function generatePDF() {  element =`<style>  img {      max-width: 100%;      max-height: 100%;      vertical-align: middle;      height: auto !important;      width: auto !important;      margin: 10px 0;    }  </style>` + element;  convertImagesToBase64(element)  .then(convertedHtml => {    // 配置选项    const opt = {      margin:       10,      filename:     '前端大法好.pdf',      image:        { type'jpeg'quality0.98 },      html2canvas:  { scale2 },      jsPDF:        { unit'mm'format'a4'orientation'portrait' }    };    // 生成PDF    html2pdf().from(convertedHtml).set(opt).save();  })  .catch(error => {    console.error('转换过程中出错:', error);  });}</script>

此时就大功告成啦!不过得提一句:图片的 URL 链接必须是同源或者允许跨越的,否则就会存在图片加载异常的问题。


阅读原文:原文链接


该文章在 2025/7/3 14:24:50 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved