前端导出pdf,所见即所得

一、推荐方案:html2canvas + jsPDF(图片式PDF)

javascript

javascript 复制代码
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

const exportPDF = async (elementId, fileName) => {
  const element = document.getElementById(elementId);
  
  // 1. 将DOM转为Canvas
  const canvas = await html2canvas(element, {
    scale: 2, // 提升清晰度
    useCORS: true, // 允许跨域图片
    logging: true, // 调试时开启
  });

  // 2. Canvas转图片数据
  const imgData = canvas.toDataURL('image/png', 1.0);
  
  // 3. 计算PDF尺寸
  const pdf = new jsPDF('p', 'mm', 'a4');
  const pageWidth = pdf.internal.pageSize.getWidth();
  const pageHeight = pdf.internal.pageSize.getHeight();
  const imgRatio = canvas.width / canvas.height;
  
  // 4. 自动适应页面大小
  let imgHeight = pageHeight;
  let imgWidth = pageWidth;
  if (pageWidth / imgRatio < pageHeight) {
    imgWidth = pageWidth;
    imgHeight = imgWidth / imgRatio;
  } else {
    imgHeight = pageHeight;
    imgWidth = imgHeight * imgRatio;
  }

  // 5. 添加图片到PDF
  pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight);
  
  // 6. 保存文件
  pdf.save(`${fileName}.pdf`);
};

// 使用示例
exportPDF('export-container', 'report');
复制代码

二、进阶方案:jsPDF内置HTML渲染(矢量文本)

javascript

javascript 复制代码
import { jsPDF } from "jspdf";

const exportPDF = async () => {
  const doc = new jsPDF('p', 'pt', 'a4');
  
  // 1. 获取需要导出的HTML元素
  const element = document.getElementById('content');
  
  // 2. 直接渲染HTML到PDF(需要配合html2canvas)
  await doc.html(element, {
    callback: (doc) => doc.save('document.pdf'),
    margin: [20, 20, 20, 20],
    autoPaging: 'text',
    width: 170, // 有效内容区宽度(mm)
    windowWidth: element.scrollWidth,
    html2canvas: {
      scale: 0.5, // 控制分辨率
      letterRendering: true,
    },
    x: 10,
    y: 10,
  });
};

三、专业方案:Puppeteer(需后端配合)

javascript

javascript 复制代码
// 前端
fetch('/generate-pdf', {
  method: 'POST',
  body: JSON.stringify({ html: document.documentElement.outerHTML }),
  headers: { 'Content-Type': 'application/json' }
});

// Node.js后端
const puppeteer = require('puppeteer');

app.post('/generate-pdf', async (req, res) => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setContent(req.body.html);
  const pdf = await page.pdf({ 
    format: 'A4',
    printBackground: true 
  });
  await browser.close();
  res.setHeader('Content-Type', 'application/pdf');
  res.send(pdf);
});

四、样式优化要点

  1. 打印样式表

css

javascript 复制代码
@media print {
  @page { margin: 0; }
  body { -webkit-print-color-adjust: exact; }
  .no-print { display: none; }
}
  1. 强制分页

css

javascript 复制代码
.page-break {
  page-break-after: always;
  break-after: page;
}
  1. 字体处理

css

javascript 复制代码
@font-face {
  font-family: 'PDFFont';
  src: url('fonts/Songti.ttf') format('truetype');
}

body {
  font-family: 'PDFFont', sans-serif;
}
复制代码

五、方案对比

方案 优点 缺点
html2canvas+jsPDF 纯前端实现,视觉保真度高 文字变图片,文件体积较大
jsPDF HTML渲染 支持矢量文字,自动分页 兼容性问题,复杂布局易出错
Puppeteer 完美还原,支持复杂CSS 需要后端支持,消耗服务器资源
window.print() 零依赖,简单快捷 样式控制能力弱,交互体验差

六、常见问题处理

  1. 内容截断

javascript

javascript 复制代码
// 手动计算分页位置
const elementHeight = element.offsetHeight;
const pageHeight = 1122; // A4像素高度(96dpi)
if (elementHeight > pageHeight) {
  // 插入分页符逻辑
}
  1. 图片跨域

html

javascript 复制代码
​
<img crossorigin="anonymous" src="https://example.com/image.jpg">

​

运行 HTML

  1. 提升清晰度

javascript

javascript 复制代码
html2canvas(element, {
  scale: 3, // 最高3倍
  dpi: 300,
  letterRendering: true
});
复制代码

根据具体需求选择方案:需要快速实现选择方案一,注重文字质量选方案二,企业级应用推荐方案三。

相关推荐
liuweidong08027 分钟前
【Pandas】pandas Series std
前端·数据库·pandas
椒盐味花生米15 分钟前
基于 React Flow 的可视化工作流
前端·react.js
关山月1 小时前
理解 Vue 3 组合式 API
前端
hx_11991 小时前
ES6-代码编程风格(数组、函数)
前端·javascript·es6
还是鼠鼠1 小时前
使用 Axios ——个人信息修改与提示框实现
前端·javascript·vscode·ajax·bootstrap·css3·html5
计算机-秋大田2 小时前
基于Spring Boot的图书个性化推荐系统的设计与实现(LW+源码+讲解)
java·前端·spring boot·后端·spring·课程设计
我不当帕鲁谁当帕鲁2 小时前
arcgis for js范围内天地图高亮,其余底图灰暗
前端·javascript·arcgis
m0_528723813 小时前
如何使用el-table的多选框
前端·javascript·vue.js
患得患失9494 小时前
【前端】【面试】【经典一道题】前端 Vue、React 采用单向数据流的原因
前端·vue.js·react.js·面试
CodeCraft Studio4 小时前
【实用技能】如何借助.NET版PDF处理控件Aspose.PDF,在 C# 中将 PDF 转换为 EPUB
pdf