
本文介绍在 flutter(支持 android 和桌面端)中将动态 html 字符串高效转为 pdf 的完整方案,涵盖核心依赖配置、异步生成逻辑、文件存储路径处理,并提供可直接运行的示例代码与关键注意事项。
本文介绍在 flutter(支持 android 和桌面端)中将动态 html 字符串高效转为 pdf 的完整方案,涵盖核心依赖配置、异步生成逻辑、文件存储路径处理,并提供可直接运行的示例代码与关键注意事项。
在 Flutter 应用中将 HTML 内容导出为 PDF 是一个常见但具有挑战性的需求,尤其当 HTML 包含内联样式、标题层级、按钮等交互元素(如 window.print())时,原生 WebView 或简单渲染组件无法直接生成可打印的 PDF 文件。Flutter 生态中,flutter_html_to_pdf 是目前稳定支持 HTML → PDF 转换的成熟方案,它基于平台原生能力(Android 使用 WebView + PrintManager,桌面端依赖系统打印 API),无需服务端参与,适合离线场景。
✅ 推荐依赖配置
在 pubspec.yaml 中添加以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_html_to_pdf: ^0.7.0
path_provider: ^2.1.1
# 若需渲染 HTML(非 PDF 导出用途),可保留:
flutter_widget_from_html_core: ^0.15.2⚠️ 注意:
flutter_html_to_pdf不支持 iOS(官方明确说明),当前仅适用于 Android 和桌面平台(Windows/macOS/Linux)。若需全平台支持,应考虑服务端渲染(如 Puppeteer)+ HTTP 下载方案。
? 核心实现:HTML 转 PDF 示例
以下是一个完整的页面组件,点击按钮即可将内置 HTML 字符串生成 PDF 并保存至临时目录:
立即学习“前端免费学习笔记(深入)”;
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_html_to_pdf/flutter_html_to_pdf.dart';
import 'package:path_provider/path_provider.dart';
class PdfPage extends StatefulWidget {
const PdfPage({super.key, required this.title});
final String title;
@override
State<PdfPage> createState() => _PdfPageState();
}
class _PdfPageState extends State<PdfPage> {
final String stringHtml = """
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: sans-serif; padding: 20px; }
h1 { color: #2c3e50; }
h2 { color: #3498db; }
button { background: #2ecc71; color: white; border: none; padding: 10px 16px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Hello, World!</h1>
<h2>Sub Hello World</h2>
<p>This is a styled HTML snippet rendered as PDF.</p>
<button onclick="window.print()">Esse Botão Vai imprimir</button>
</body>
</html>
""";
Future<void> _generatePDF() async {
try {
final Directory tempDir = await getTemporaryDirectory();
final String outputPath = tempDir.path;
final File? pdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(
stringHtml,
outputPath,
"exported_report", // 文件名(无扩展名,自动加 .pdf)
);
if (pdfFile != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('✅ PDF saved: ${pdfFile.path}')),
);
print('PDF generated at: ${pdfFile.path}');
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('❌ PDF generation returned null')),
);
}
} catch (e, stackTrace) {
print('Error generating PDF: $e\n$stackTrace');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('⚠️ Failed to generate PDF')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
icon: const Icon(Icons.picture_as_pdf),
onPressed: _generatePDF,
tooltip: 'Export as PDF',
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Preview (rendered via flutter_widget_from_html_core):',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
// 可选:使用 HtmlWidget 预览效果(需额外引入包)
// HtmlWidget(stringHtml, textStyle: const TextStyle(fontSize: 14)),
const Divider(),
ElevatedButton.icon(
icon: const Icon(Icons.download_outlined),
label: const Text('Convert & Save PDF'),
onPressed: _generatePDF,
),
const SizedBox(height: 16),
Text.rich(
TextSpan(children: [
const TextSpan(text: '? Tip: ', style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(text: 'Generated PDFs are stored in the system temporary directory. For persistent storage (e.g., Downloads folder), use getApplicationDocumentsDirectory() instead.'),
]),
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
);
}
}? 关键注意事项
-
权限要求(Android):确保
AndroidManifest.xml中声明存储权限(尤其 Android 10+):<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <!-- Android 11+ 建议使用分区存储,临时目录无需权限 -->
-
桌面端兼容性:Windows/macOS 上需启用桌面支持(
flutter config --enable-windows-desktop等),且系统需安装默认 PDF 打印驱动。 -
HTML 限制:JavaScript(如
onclick)在 PDF 生成过程中不会执行;window.print()仅对浏览器有效,在 PDF 输出中表现为静态文本/按钮。样式建议以内联<style></style>或属性方式定义,避免外部 CSS 文件引用。 -
替代方案提示:若需更高精度排版(如分页控制、页眉页脚、CSS Paged Media),建议接入 Web 技术栈(例如:用
flutter_webview_plugin加载 HTML 页面后调用print(),或通过http请求后端 Puppeteer 服务生成 PDF)。
通过以上方案,你可在 Flutter 安卓及桌面应用中快速实现 HTML 到 PDF 的本地化、零依赖导出,兼顾开发效率与运行可靠性。



















