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

Flutter WebView无法显示/下载PDF的解决方案咨询

在Flutter应用内通过flutter_inappwebview实现PDF下载并打开

核心思路

利用flutter_inappwebview的下载监听回调拦截PDF下载请求,通过网络库将文件下载到本地存储,再调用PDF查看组件在应用内完成打开操作。

步骤1:添加依赖

在pubspec.yaml中引入所需依赖包:

dependencies:
  flutter_inappwebview: ^6.0.0 # 建议使用最新稳定版本
  dio: ^5.0.0
  path_provider: ^2.0.0
  open_file: ^3.0.0 # 若需内嵌查看可替换为flutter_pdfview

步骤2:实现下载与打开逻辑

在InAppWebView组件中配置下载监听,拦截PDF请求并处理下载流程:

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';

class PDFDownloadPage extends StatefulWidget {
  @override
  _PDFDownloadPageState createState() => _PDFDownloadPageState();
}

class _PDFDownloadPageState extends State<PDFDownloadPage> {
  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('PDF下载测试')),
      body: InAppWebView(
        initialUrlRequest: URLRequest(
          url: Uri.parse('https://www.wmata.com/schedules/maps/upload/2019-System-Map.pdf'),
        ),
        onWebViewCreated: (controller) => webViewController = controller,
        downloadListener: (DownloadTask task) async {
          // 仅拦截PDF格式的下载请求
          if (task.url.path.endsWith('.pdf')) {
            await _handlePDFDownload(task.url.toString());
          }
        },
      ),
    );
  }

  Future<void> _handlePDFDownload(String pdfUrl) async {
    try {
      // 获取本地存储目录
      Directory? storageDir;
      if (Platform.isAndroid) {
        storageDir = await getExternalStorageDirectory();
      } else if (Platform.isIOS) {
        storageDir = await getApplicationDocumentsDirectory();
      }
      if (storageDir == null) return;

      // 生成文件存储路径
      final fileName = pdfUrl.split('/').last;
      final savePath = '${storageDir.path}/$fileName';
      final targetFile = File(savePath);

      // 使用Dio执行下载
      final dio = Dio();
      await dio.download(
        pdfUrl,
        targetFile.path,
        onReceiveProgress: (count, total) {
          // 可在此添加下载进度提示逻辑
          print('下载进度:${(count / total * 100).toStringAsFixed(0)}%');
        },
      );

      // 下载完成后打开PDF
      await OpenFile.open(targetFile.path);
    } catch (e) {
      print('下载失败:$e');
      // 可在此添加错误提示UI
    }
  }
}

步骤3:配置平台权限

  • Android:在android/app/src/main/AndroidManifest.xml中添加存储权限(Android 13+下载到应用私有目录无需额外动态申请):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
  • iOS:在Info.plist中添加文件访问权限声明:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>

关键说明

  • 通过flutter_inappwebview的downloadListener直接拦截请求,无需跳转外部浏览器。
  • 下载到应用私有目录更安全,避免权限申请复杂流程。
  • 若需内嵌查看PDF,可替换open_file为flutter_pdfview,将下载后的文件路径传入PDFView组件即可实现内嵌预览。

内容的提问来源于stack exchange,提问作者Roman Soviak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:35:11