JS 如何将 HTML 页面导出为 PDF

本文介绍了一种使用jsPDF和html2canvas将HTML页面导出为PDF的方法。解决了常见问题如导出空白PDF,并分享了一个成功的示例项目。
该文章已生成可运行项目,

2017年7月21日更新

没想到我为实现自己需求写的Demo受到这么多人关注,私信问的比较多。

在这里向大家道歉了,因为这个Demo是有瑕疵的,比如它不支持多页(我的需求只是一页ε=ε=ε=┏(゜ロ゜;)┛),页面拉伸,模糊等问题

为了避免更多人被我误导,建议大佬们参考以下教程文档:

  • http://rawgit.com/MrRio/jsPDF/master/
    这是官方案例,其中有个 HTMLRender 案例便是导出多页PDF的最简单的方式

    var doc = new jsPDF();
    
    // We'll make our own renderer to skip this editor
    var specialElementHandlers = {
        '#editor': function(element, renderer){
            return true;
        }
    };
    
    // All units are in the set measurement for the document
    // This can be changed to "pt" (points), "mm" (Default), "cm", "in"
    doc.fromHTML($('body').get(0), 15, 15, {
        'width': 170, 
        'elementHandlers': specialElementHandlers
    });
    
  • https://github.com/linwalker/render-html-to-pdf

    这个是结合html2canvas和jspdf导出多页的详细解释demo,写的比我好太多,而且实现逻辑很高明。

下面是我的正文,/(ㄒoㄒ)/~~


好久没在优快云写博客了,因为都放在了个人网站了哈

我这里有个需求,就是前端添加个按钮,提供HTML页面导出为PDF的功能。

我谷歌了好久(难道是我谷歌的方式不对 (ˉ▽ˉ;)…),找到的答案大都推荐 jsPDF + html2canvas 的方式。

参考了这两个开源项目的文档,自己写,失败,导出的pdf是空的。
参考 stackoverflow 代码,同样失败,同样只导出空白的pdf,他们咋成功了?

好了,以上都是废话,只是说明了我找答案的艰辛之旅。

源码在这里 https://github.com/pwcong/how-transform-html-into-pdf

栗子

准备

创建项目文件夹,npm构建怎样都行,我这里简单直接引入两个库 jspdfhtml2canvas,大家可以自行下载。

新建HTML页面文件

头部引入刚才所下载的 jspdfhtml2canvas,再导入主要的 js 文件例如:

<script src="/js/jspdf.debug.js"></script>
<script src="/js/html2canvas.js"></script>
<script src="/main.js"></script>

页面里面内容自己想怎么写就怎么写啦,提供一个按钮来触发导出pdf的功能,例如:


<button id="btn-html2canvas">export PDF by using jspdf + html2canvas</button>

编辑 main.js

document.getElementById("btn-html2canvas").onclick = function(){

    html2canvas(document.getElementById("content"), {
        onrendered: function(canvas) {

            //通过html2canvas将html渲染成canvas,然后获取图片数据
            var imgData = canvas.toDataURL('image/jpeg');

            //初始化pdf,设置相应格式
            var doc = new jsPDF("p", "mm", "a4");

            //这里设置的是a4纸张尺寸
            doc.addImage(imgData, 'JPEG', 0, 0,210,297);

            //输出保存命名为content的pdf
            doc.save('content.pdf');
        }
    });

}

这里要特别注意 canvas.toDataURL('image/jpeg)的参数 image/jpegdoc.addImage(...,'JPEG',...) 的参数 JPEG务必一致
而且,我也建议这两个参数分别写 image/jpegJPEG
因为其他参数例如 image/png 等,导出pdf后内容为空。
这也是困扰了我一天的问题。(我猜测因为html2canvas输出的图片base64数据是image/jpeg格式,如果写其他格式会导致渲染失败)

添加到服务器中浏览器访问,测试html导出为pdf是否成功,总之博主成功了。

本文章已经生成可运行项目
在 React 应用中实现将页面内容导出PDF 文件的功能,通常可以通过以下几种方式实现: 1. **使用 `html2canvas` 和 `jsPDF` 库** 该方法的基本思路是先将页面内容渲染为画布图像,然后将图像插入到 PDF 文档中。这种方式适合需要将页面可视区域导出PDF 的场景。 安装依赖: ```bash npm install html2canvas jspdf ``` 示例代码: ```javascript import html2canvas from 'html2canvas'; import jsPDF from 'jspdf'; const exportToPDF = () => { const input = document.getElementById('content-to-export'); // 获取要导出的 DOM 元素 html2canvas(input).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const imgWidth = 210; // A4 纸张宽度 const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight); pdf.save('page-export.pdf'); }); }; ``` 调用组件中的按钮触发导出: ```jsx <div id="content-to-export"> {/* 页面内容 */} </div> <button onClick={exportToPDF}>导出PDF</button> ``` 2. **使用 `react-pdf/renderer` 渲染原生 PDF 内容** 如果需要更精细地控制 PDF 的布局和样式,可以使用 [react-pdf/renderer](https://www.npmjs.com/package/@react-pdf/renderer)。它允许使用 React 组件语法构建 PDF 文档。 安装依赖: ```bash npm install @react-pdf/renderer ``` 示例代码: ```jsx import React from 'react'; import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer'; // Create styles const styles = StyleSheet.create({ page: { flexDirection: 'row', backgroundColor: '#E4E4E4' }, section: { margin: 10, padding: 10, flexGrow: 1 } }); // Create Document Component const MyDocument = () => ( <Document> <Page size="A4" style={styles.page}> <View style={styles.section}> <Text>这是一个 PDF 页面内容</Text> </View> </Page> </Document> ); export default MyDocument; ``` 使用 `PDFDownloadLink` 提供下载功能: ```jsx import { PDFDownloadLink } from '@react-pdf/renderer'; const ExportPDFButton = () => ( <PDFDownloadLink document={<MyDocument />} fileName="react-pdf-export.pdf"> {({ loading }) => (loading ? '加载中...' : '导出PDF')} </PDFDownloadLink> ); ``` 3. **结合后端生成 PDF(如 Puppeteer)** 对于复杂的页面结构或需要高保真渲染的场景,可以借助后端服务,例如使用 Node.js 的 [Puppeteer](https://pptr.dev/) 生成 PDF。前端发送页面内容或 URL 给后端,由 Puppeteer 在无头浏览器中渲染页面并生成 PDF。 示例后端(Node.js + Express + Puppeteer): ```javascript const express = require('express'); const puppeteer = require('puppeteer'); const app = express(); app.get('/generate-pdf', async (req, res) => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://your-react-app.com/page-to-export', { waitUntil: 'networkidle2' }); const pdf = await page.pdf({ format: 'A4' }); await browser.close(); res.contentType('application/pdf'); res.send(pdf); }); app.listen(3000, () => console.log('Server running on port 3000')); ``` 前端调用: ```javascript const downloadPDF = async () => { const response = await fetch('http://localhost:3000/generate-pdf'); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'react-page-export.pdf'; a.click(); window.URL.revokeObjectURL(url); }; ``` ### 总结 - **前端直接导出**:推荐使用 `html2canvas` + `jsPDF` 或 `react-pdf/renderer`,适合大多数前端导出需求。 - **复杂场景或高保真导出**:建议结合后端工具如 Puppeteer 实现更稳定的 PDF 生成。
评论 50
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值