Flutter Web下如何将HTML内容转为PDF?不支持flutter_html_to_pdf
Flutter Web 实现HTML转PDF方案
针对Flutter Web环境下无法使用flutter_html_to_pdf的问题,提供两种可行实现方式:
方法一:通过JS库(jsPDF + html2canvas)实现
利用浏览器原生JS能力,将HTML转为图片后生成PDF,适合复杂HTML内容,渲染效果与浏览器一致。
步骤1:引入JS库
将jspdf和html2canvas的本地文件放入web/js目录,然后在web/index.html中添加:
<script src="js/jspdf.umd.min.js"></script> <script src="js/html2canvas.min.js"></script>
步骤2:编写Dart工具类
通过dart:js调用JS逻辑:
import 'dart:js' as js; class HtmlToPdfConverter { static Future<void> generatePdf(String htmlContent) async { js.context.callMethod('eval', [''' // 创建临时容器存放HTML const tempContainer = document.createElement('div'); tempContainer.innerHTML = `$htmlContent`; document.body.appendChild(tempContainer); // 将HTML转为画布再生成PDF html2canvas(tempContainer).then(canvas => { const pdf = new jspdf.jsPDF('p', 'mm', 'a4'); const pageWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pageWidth; const imgHeight = (canvas.height * imgWidth) / canvas.width; let remainingHeight = imgHeight; let currentY = 0; // 添加第一页 pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, currentY, imgWidth, imgHeight); remainingHeight -= pdf.internal.pageSize.getHeight(); // 处理分页 while (remainingHeight >= 0) { currentY = remainingHeight - imgHeight; pdf.addPage(); pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, currentY, imgWidth, imgHeight); remainingHeight -= pdf.internal.pageSize.getHeight(); } // 下载PDF并清理临时元素 pdf.save('output.pdf'); document.body.removeChild(tempContainer); }); ''']); } }
调用方式
final htmlContent = '<p>sample text</p><p><b>sample text</b></p><p><i><b>sample text</b></i><br></p>'; await HtmlToPdfConverter.generatePdf(htmlContent);
方法二:纯Dart实现(pdf + printing库)
通过解析HTML节点,手动构建PDF内容,适合结构简单的HTML,无需依赖JS。
步骤1:添加依赖
在pubspec.yaml中添加:
dependencies: pdf: ^3.10.0 printing: ^6.2.0 html: ^0.15.4
步骤2:编写转换逻辑
import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; import 'package:html/parser.dart' as parser; import 'package:html/dom.dart' as dom; Future<void> convertHtmlToPdf(String html) async { final pdfDoc = pw.Document(); final dom.Document htmlDoc = parser.parse(html); // 遍历HTML段落节点,转换为PDF文本组件 for (final element in htmlDoc.body!.children) { if (element is dom.Element && element.localName == 'p') { final text = element.text; final hasBold = element.querySelector('b') != null; final hasItalic = element.querySelector('i') != null; pdfDoc.addPage( pw.Page( build: (context) => pw.Container( padding: pw.EdgeInsets.all(16), child: pw.Text( text, style: pw.TextStyle( fontWeight: hasBold ? pw.FontWeight.bold : pw.FontWeight.normal, fontStyle: hasItalic ? pw.FontStyle.italic : pw.FontStyle.normal, fontSize: 14, ), ), ), ), ); } } // 导出PDF await Printing.sharePdf(bytes: await pdfDoc.save(), filename: 'output.pdf'); }
调用方式
final htmlContent = '<p>sample text</p><p><b>sample text</b></p><p><i><b>sample text</b></i><br></p>'; await convertHtmlToPdf(htmlContent);
两种方案对比
- 方法一:渲染效果还原度高,支持复杂HTML(含样式、图片),但依赖浏览器JS环境。
- 方法二:纯Dart跨平台,无需额外JS资源,但需要手动处理HTML节点,对复杂结构适配成本高。
内容的提问来源于stack exchange,提问作者Fevzettin AYDIN
相关产品推荐
相关产品推荐

