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

Flutter应用内打开网页无法下载PDF文件问题求助

解决Flutter应用内网页PDF点击无响应的问题

问题分析

你当前使用url_launcher的launchUrl方法跳转网页,虽能正常打开页面,但网页内的PDF链接点击无反应;外部浏览器打开同一URL则可正常下载PDF。由于PDF文件数量较多,无法逐个使用文件直链,因此通过flutter_inappwebview包实现应用内网页加载并处理PDF下载是最优方案。

解决方案步骤

1. 添加依赖

在pubspec.yaml中引入flutter_inappwebview包:

dependencies:
  flutter:
    sdk: flutter
  flutter_inappwebview: ^6.0.0 # 建议使用最新版本

执行flutter pub get完成依赖安装。

2. 修改按钮跳转逻辑

将原来的launchUrl跳转改为打开内嵌WebView页面,调整按钮的onPressed代码:

FloatingActionButton.large(
  backgroundColor: Color.fromRGBO(136, 221, 198, 1),
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => WebViewPage(url: 'https://www.agricultura.rs.gov.br/agrometeorologia'),
      ),
    );
  },
  child: Image(
    image: AssetImage("assets/book.png"),
    height: size.height * .1,
  ),
),

3. 创建WebView页面并配置PDF下载处理

新建WebViewPage组件,通过InAppWebView加载网页,并监听下载请求处理PDF文件:

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

class WebViewPage extends StatefulWidget {
  final String url;

  const WebViewPage({Key? key, required this.url}) : super(key: key);

  @override
  State<WebViewPage> createState() => _WebViewPageState();
}

class _WebViewPageState extends State<WebViewPage> {
  InAppWebViewController? webViewController;
  final GlobalKey webViewKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Leitura Complementar')),
      body: InAppWebView(
        key: webViewKey,
        initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
        onWebViewCreated: (controller) {
          webViewController = controller;
        },
        onDownloadStartRequest: (controller, downloadStartRequest) async {
          // 获取下载链接与文件名
          final downloadUrl = downloadStartRequest.url;
          final fileName = downloadUrl.pathSegments.last;

          // 获取设备存储目录
          final storageDir = await getExternalStorageDirectory();
          if (storageDir == null) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('无法获取存储目录')),
            );
            return;
          }

          final filePath = '${storageDir.path}/$fileName';
          // 触发文件下载
          await controller.downloadFile(
            url: downloadUrl,
            destinationFilePath: filePath,
            onDownloadProgress: (progress) {
              // 可选:打印下载进度
              print('下载进度: ${(progress.progress * 100).round()}%');
            },
          );

          // 下载完成提示用户
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('文件已下载至: $filePath')),
          );
        },
      ),
    );
  }
}

4. 配置平台权限

  • Android:在android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • iOS:在ios/Runner/Info.plist中添加配置:
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>

原理说明

flutter_inappwebview提供了完整的网页加载控制能力,通过onDownloadStartRequest回调可捕获网页内所有下载请求(包括PDF链接)。我们在回调中处理文件存储路径、下载进度提示和完成通知,解决了原生跳转无法处理内嵌网页PDF下载的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:11:02