html-pdf 中文教程

1. 项目概述

html-pdf 是一个基于 Node.js 的 HTML 到 PDF 转换工具,它使用 PhantomJS 来渲染 HTML 内容并生成 PDF 文档。它提供了简单易用的 API,允许开发者将静态 HTML 或动态生成的 HTML 转换为高质量的 PDF 文档。

2. 核心功能

2.1 基本功能

  • HTML 转换:将 HTML 文件或字符串转换为 PDF 文档
  • CSS 支持:支持内联 CSS、外部 CSS 文件和 CSS 框架
  • 页面设置:设置页面大小、边距、方向等
  • 页眉页脚:添加和设置页眉页脚
  • 页面编号:在页眉页脚中添加页码
  • 输出选项:保存为文件或返回缓冲区

2.2 高级功能

  • 自定义字体:添加和使用自定义字体
  • 图片支持:处理 HTML 中的图片
  • JavaScript 支持:执行 HTML 中的 JavaScript 代码
  • 延迟渲染:等待指定时间或事件后再渲染
  • 水印功能:添加水印到 PDF 文档
  • 加密选项:设置 PDF 文档的密码和权限

3. 安装与设置

3.1 在 Node.js 环境中安装

npm install html-pdf

3.2 基本配置

html-pdf 不需要额外的配置,但需要注意它依赖于 PhantomJS,安装过程中会自动下载。

4. 基本使用示例

4.1 转换 HTML 文件

// 导入库
const pdf = require('html-pdf');
const fs = require('fs');

// 读取 HTML 文件
const html = fs.readFileSync('path/to/file.html', 'utf8');

// 设置转换选项
const options = {
  format: 'A4',
  orientation: 'portrait',
  border: '10mm',
  timeout: 30000 // 30秒超时
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('output.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('PDF 文档创建成功:', res.filename);
});

4.2 转换 HTML 字符串

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = `
<!DOCTYPE html>
<html>
<head>
  <title>测试文档</title>
  <style>
    body { font-family: Arial, sans-serif; }
    h1 { color: #333; }
    .container { padding: 20px; }
  </style>
</head>
<body>
  <div class="container">
    <h1>Hello World!</h1>
    <p>这是使用 html-pdf 库创建的 PDF 文档。</p>
  </div>
</body>
</html>
`;

// 设置转换选项
const options = {
  format: 'Letter',
  border: {
    top: '1in',
    right: '1in',
    bottom: '1in',
    left: '1in'
  }
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('test.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('PDF 文档创建成功:', res.filename);
});

4.3 获取 PDF 缓冲区

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = '<h1>Hello World!</h1><p>这是一个测试文档。</p>';

// 设置转换选项
const options = {
  format: 'A4'
};

// 转换为缓冲区
pdf.create(html, options).toBuffer((err, buffer) => {
  if (err) return console.error(err);
  console.log('PDF 缓冲区创建成功,大小:', buffer.length, '字节');
  // 可以将缓冲区发送给客户端或进行其他处理
});

4.4 使用 Promise 接口

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = '<h1>Hello World!</h1><p>这是一个测试文档。</p>';

// 设置转换选项
const options = {
  format: 'A4'
};

// 使用 Promise 接口
pdf.create(html, options).toFile('output.pdf')
  .then(res => {
    console.log('PDF 文档创建成功:', res.filename);
  })
  .catch(err => {
    console.error('创建 PDF 文档时出错:', err);
  });

5. 高级用法

5.1 设置页眉页脚

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = `
<!DOCTYPE html>
<html>
<head>
  <title>测试文档</title>
  <style>
    body { font-family: Arial, sans-serif; }
    h1 { color: #333; }
    .container { padding: 20px; }
  </style>
</head>
<body>
  <div class="container">
    <h1>Hello World!</h1>
    <p>这是使用 html-pdf 库创建的 PDF 文档。</p>
    <p>页面 1 内容</p>
    <div style="page-break-after: always;"></div>
    <p>页面 2 内容</p>
  </div>
</body>
</html>
`;

// 设置转换选项
const options = {
  format: 'A4',
  border: {
    top: '40px',
    right: '20px',
    bottom: '40px',
    left: '20px'
  },
  header: {
    height: '30px',
    contents: '<div style="text-align: center; font-size: 10px;">文档页眉</div>'
  },
  footer: {
    height: '30px',
    contents: {
      default: '<div style="text-align: center; font-size: 10px;">页码: {{page}} / {{pages}}</div>'
    }
  }
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('header-footer-example.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('带页眉页脚的 PDF 文档创建成功:', res.filename);
});

5.2 使用自定义字体

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = `
<!DOCTYPE html>
<html>
<head>
  <title>测试文档</title>
  <style>
    @font-face {
      font-family: 'CustomFont';
      src: url('path/to/font.ttf');
    }
    body { font-family: 'CustomFont', Arial, sans-serif; }
    h1 { color: #333; }
  </style>
</head>
<body>
  <h1>Hello World!</h1>
  <p>这是使用自定义字体的 PDF 文档。</p>
</body>
</html>
`;

// 设置转换选项
const options = {
  format: 'A4'
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('custom-font-example.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('带自定义字体的 PDF 文档创建成功:', res.filename);
});

5.3 处理图片

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = `
<!DOCTYPE html>
<html>
<head>
  <title>测试文档</title>
  <style>
    body { font-family: Arial, sans-serif; }
    h1 { color: #333; }
    .container { padding: 20px; }
    img { max-width: 100%; height: auto; }
  </style>
</head>
<body>
  <div class="container">
    <h1>图片示例</h1>
    <p>这是一张图片:</p>
    <img src="path/to/image.jpg" alt="测试图片">
    <p>图片下方的文字</p>
  </div>
</body>
</html>
`;

// 设置转换选项
const options = {
  format: 'A4'
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('image-example.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('带图片的 PDF 文档创建成功:', res.filename);
});

5.4 使用 JavaScript

// 导入库
const pdf = require('html-pdf');

// HTML 字符串
const html = `
<!DOCTYPE html>
<html>
<head>
  <title>测试文档</title>
  <style>
    body { font-family: Arial, sans-serif; }
    h1 { color: #333; }
    .container { padding: 20px; }
    .dynamic-content { margin-top: 20px; padding: 10px; background: #f0f0f0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>JavaScript 示例</h1>
    <p>这是一个使用 JavaScript 的 PDF 文档。</p>
    <div class="dynamic-content" id="dynamicContent"></div>
  </div>
  <script>
    // 动态生成内容
    document.getElementById('dynamicContent').innerHTML = '<p>这是由 JavaScript 动态生成的内容</p><p>当前时间: ' + new Date().toLocaleString() + '</p>';
  </script>
</body>
</html>
`;

// 设置转换选项
const options = {
  format: 'A4',
  renderDelay: 1000 // 延迟 1 秒以确保 JavaScript 执行完成
};

// 转换并保存为 PDF 文件
pdf.create(html, options).toFile('javascript-example.pdf', (err, res) => {
  if (err) return console.error(err);
  console.log('带 JavaScript 的 PDF 文档创建成功:', res.filename);
});

6. 实际应用场景

6.1 生成报告

使用 html-pdf 库从数据库或 API 获取数据,生成包含表格、图表和格式化文本的专业报告。

6.2 自动化文档生成

根据用户输入或模板自动生成个性化文档,如合同、发票、简历等。

6.3 教育内容创建

为在线课程生成包含教程内容、练习和答案的 PDF 文档。

6.4 商业文档管理

创建和管理企业内部文档,如员工手册、政策文档、培训材料等。

6.5 票据生成

生成各种票据,如发票、收据、门票等,包含条形码或二维码。

7. 代码优化建议

7.1 模块化设计

将 PDF 生成逻辑拆分为多个模块,提高代码可维护性:

// PDF 生成器模块
class PdfGenerator {
  constructor() {
    this.pdf = require('html-pdf');
  }

  createPdf(html, options) {
    return new Promise((resolve, reject) => {
      this.pdf.create(html, options).toFile((err, res) => {
        if (err) reject(err);
        else resolve(res);
      });
    });
  }

  createReport(data, template) {
    // 渲染模板
    const html = this.renderTemplate(template, data);
    
    // 设置选项
    const options = {
      format: 'A4',
      border: '10mm'
    };
    
    return this.createPdf(html, options);
  }

  renderTemplate(template, data) {
    // 简单的模板渲染逻辑
    let html = template;
    for (const key in data) {
      html = html.replace(new RegExp(`{{${key}}}`, 'g'), data[key]);
    }
    return html;
  }
}

// 使用示例
const generator = new PdfGenerator();
const data = {
  title: '销售报告',
  date: new Date().toLocaleDateString(),
  sales: '10000'
};
const template = '<h1>{{title}}</h1><p>日期: {{date}}</p><p>销售额: {{sales}}</p>';

generator.createReport(data, template)
  .then(res => {
    console.log('报告生成成功:', res.filename);
  })
  .catch(err => {
    console.error('生成报告时出错:', err);
  });

7.2 错误处理

添加适当的错误处理,提高代码健壮性:

try {
  const pdf = require('html-pdf');
  const html = '<h1>Hello World!</h1>';
  const options = { format: 'A4' };
  
  pdf.create(html, options).toFile('document.pdf', (err, res) => {
    if (err) {
      console.error('创建 PDF 文档时出错:', err);
      // 处理错误
      return;
    }
    console.log('PDF 文档创建成功:', res.filename);
  });
} catch (error) {
  console.error('初始化 PDF 生成器时出错:', error);
  // 处理错误
}

7.3 性能优化

对于大型 PDF 文档,使用异步操作和适当的超时设置:

async function generateLargePdf(html, filename) {
  try {
    const pdf = require('html-pdf');
    
    const options = {
      format: 'A4',
      timeout: 60000, // 增加超时时间
      renderDelay: 2000 // 增加渲染延迟
    };
    
    return new Promise((resolve, reject) => {
      pdf.create(html, options).toFile(filename, (err, res) => {
        if (err) reject(err);
        else resolve(res);
      });
    });
  } catch (error) {
    console.error('生成大型 PDF 文档时出错:', error);
    throw error;
  }
}

// 使用示例
generateLargePdf(largeHtml, 'large-document.pdf')
  .then(res => {
    console.log('大型 PDF 文档生成成功:', res.filename);
  })
  .catch(err => {
    console.error('生成大型 PDF 文档时出错:', err);
  });

7.4 内存管理

对于大型 HTML 内容,注意内存使用:

// 避免一次性加载大型 HTML 文件到内存
function generatePdfFromStream(stream, filename) {
  const pdf = require('html-pdf');
  let html = '';
  
  stream.on('data', chunk => {
    html += chunk;
  });
  
  stream.on('end', () => {
    const options = {
      format: 'A4'
    };
    
    pdf.create(html, options).toFile(filename, (err, res) => {
      if (err) return console.error(err);
      console.log('PDF 文档创建成功:', res.filename);
      // 释放内存
      html = null;
    });
  });
  
  stream.on('error', error => {
    console.error('读取流时出错:', error);
  });
}

8. 总结

html-pdf 是一个功能强大、灵活易用的 Node.js 库,为开发者提供了将 HTML 转换为 PDF 文档的能力。它的主要优势包括:

  • 易于使用:简单的 API 设计,易于与现有项目集成
  • 功能丰富:支持从基本 HTML 转换到复杂的页眉页脚、自定义字体等
  • 高度可定制:支持多种配置选项和高级功能
  • 稳定可靠:基于 PhantomJS 的成熟技术

通过本教程的学习,您应该已经掌握了 html-pdf 的基本用法和一些高级技巧,可以开始在实际项目中应用它来生成 PDF 文档了。

9. 参考资源

« 上一篇 pdfmake 中文教程 下一篇 » markdown-pdf 中文教程