Flutter Web中HTML转PDF并下载的实现示例请求
Flutter Web: 把WebView里的HTML转成PDF下载
在Flutter Web环境下,很多PDF生成包要么不兼容Web,要么没法很好地还原WebView里的HTML样式。这里给你一套基于JS交互的可行方案,直接利用浏览器能力完成转换和下载:
步骤1:配置WebView并添加下载按钮
使用webview_flutter包(请使用支持Web的版本,比如^4.4.0)加载HTML内容,同时启用JavaScript,再添加触发下载的按钮:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'dart:js' as js; class HtmlPreviewPage extends StatefulWidget { final String htmlContent; const HtmlPreviewPage({super.key, required this.htmlContent}); @override State<HtmlPreviewPage> createState() => _HtmlPreviewPageState(); } class _HtmlPreviewPageState extends State<HtmlPreviewPage> { late WebViewController webController; @override void initState() { super.initState(); webController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..loadHtmlString(widget.htmlContent); } // 核心逻辑:调用JS生成并下载PDF void downloadAsPdf() async { await webController.runJavaScript(''' // 优先用Chromium内核浏览器原生API,样式还原度最高 if (window.chrome?.printToPDF) { window.chrome.printToPDF({ printBackground: true, // 确保背景样式被包含 margin: {top: 10, bottom: 10, left: 10, right: 10}, landscape: false }).then(pdfData => { const blob = new Blob([pdfData], {type: 'application/pdf'}); const downloadUrl = URL.createObjectURL(blob); const aTag = document.createElement('a'); aTag.href = downloadUrl; aTag.download = 'html_preview.pdf'; aTag.click(); URL.revokeObjectURL(downloadUrl); }); } else { // 非Chromium浏览器降级方案:用html2canvas+jsPDF // 注意:这两个库的代码要提前内嵌到加载的HTML中(不要用外部CDN) html2canvas(document.body, {scale: 2}).then(canvas => { const pdf = new jsPDF('p', 'mm', 'a4'); const imgWidth = 210; const imgHeight = canvas.height * imgWidth / canvas.width; pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, imgWidth, imgHeight); pdf.save('html_preview.pdf'); }); } '''); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HTML预览'), actions: [ IconButton( icon: const Icon(Icons.download), onPressed: downloadAsPdf, tooltip: '下载为PDF', ), ], ), body: WebViewWidget(controller: webController), ); } }
步骤2:处理非Chromium浏览器的兼容
如果用户使用Firefox等不支持chrome.printToPDF的浏览器,需要把html2canvas和jsPDF的压缩代码直接内嵌到你要加载的HTML中,示例HTML结构如下:
// 示例内嵌了JS库的HTML内容 final htmlContent = ''' <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> /* 你的自定义样式 */ body { padding: 20px; font-family: Arial, sans-serif; } .highlight { color: red; font-weight: bold; } </style> <!-- 内嵌html2canvas的压缩代码(直接从官网复制min版内容) --> <script> // 粘贴html2canvas.min.js的代码 </script> <!-- 内嵌jsPDF的压缩代码(直接从官网复制min版内容) --> <script> // 粘贴jspdf.min.js的代码 </script> </head> <body> <h1>测试标题</h1> <p class="highlight">这是带样式的测试文本</p> <p>更多内容...</p> </body> </html> ''';
关键注意事项
- 必须开启WebView的JavaScript权限(
JavaScriptMode.unrestricted),否则JS代码无法执行。 chrome.printToPDF仅支持Chromium内核浏览器(Chrome、Edge、Brave等),生成的PDF能完整还原HTML样式,包括背景色、复杂布局。- 降级方案是把HTML转成图片再生成PDF,样式还原度略逊,但兼容性覆盖更多浏览器。
内容的提问来源于stack exchange,提问作者FF dev
相关产品推荐
相关产品推荐

