You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
''';

关键注意事项

  1. 必须开启WebView的JavaScript权限(JavaScriptMode.unrestricted),否则JS代码无法执行。
  2. chrome.printToPDF仅支持Chromium内核浏览器(Chrome、Edge、Brave等),生成的PDF能完整还原HTML样式,包括背景色、复杂布局。
  3. 降级方案是把HTML转成图片再生成PDF,样式还原度略逊,但兼容性覆盖更多浏览器。

内容的提问来源于stack exchange,提问作者FF dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:45:24