如何在flutter中通过webview下载/创建pdf

Posted

技术标签:

【中文标题】如何在flutter中通过webview下载/创建pdf【英文标题】:how to download/create pdf through webview in flutter 【发布时间】:2019-10-08 09:27:52 【问题描述】:

我创建了一个 webviewscaffold,但在从 webview 浏览时无法从中下载任何内容,我创建了但是当我单击按钮时它什么也不做。我不知道从哪里开始,就像在其他可以下载和预览的浏览器中一样,我正在尝试在这里实现相同的目标。

class AppState extends State<App> 


  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Stack(
        children: <Widget>[
          Align(
            alignment: Alignment(1, 1),
            child: Container(
              child: Web(), // it is a statefulwidget that have WebviewScaffold, i have created it on a new page and imported/used here
            ),
          ),
          Column(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Padding(
                padding: EdgeInsets.only(top: 20.0),
              )
            ],
          ),
          Align(
            alignment: Alignment(0.7, -0.93),
            child: FloatingActionButton(
                tooltip: "Share",
                child: Icon(
                  Icons.share,
                  color: Colors.amberAccent,
                ),
                onPressed: () 
                  _onShareTap();
                ),
          ),
        ],
      ),
    );
  

我希望,当我单击 web 视图中的打印或下载按钮时,它应该像任何其他浏览器一样工作。

【问题讨论】:

@user10182490 你找到解决办法了吗? 【参考方案1】:

你可以使用我的插件flutter_inappwebview,这是一个 Flutter 插件,允许你添加内联 WebViews 或打开一个应用内浏览器窗口,并且有很多事件、方法和选项来控制 WebViews。

为了能够识别可下载的文件,您需要设置useOnDownloadStart: true 选项,然后您才能监听onDownloadStart 事件!

另外,例如,在 android 上,您需要在 AndroidManifest.xml 文件中添加写入权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

然后,您需要使用permission_handler 插件请求许可。相反,为了有效地下载您的文件,您可以使用flutter_downloader 插件。

这是一个使用http://ovh.net/files/(特别是http://ovh.net/files/1Mio.dat作为URL)测试下载的完整示例:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

Future main() async 
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterDownloader.initialize(
      debug: true // optional: set false to disable printing logs to console
  );
  await Permission.storage.request();
  runApp(new MyApp());


class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => new _MyAppState();


class _MyAppState extends State<MyApp> 
  InAppWebViewController webView;

  @override
  void initState() 
    super.initState();
  

  @override
  void dispose() 
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('InAppWebView Example'),
        ),
        body: Container(
            child: Column(children: <Widget>[
          Expanded(
              child: InAppWebView(
            initialUrl: "http://ovh.net/files/1Mio.dat",
            initialHeaders: ,
            initialOptions: InAppWebViewGroupOptions(
              crossPlatform: InAppWebViewOptions(
                debuggingEnabled: true,
                useOnDownloadStart: true
              ),
            ),
            onWebViewCreated: (InAppWebViewController controller) 
              webView = controller;
            ,
            onLoadStart: (InAppWebViewController controller, String url) 

            ,
            onLoadStop: (InAppWebViewController controller, String url) 

            ,
            onDownloadStart: (controller, url) async 
              print("onDownloadStart $url");
              final taskId = await FlutterDownloader.enqueue(
                url: url,
                savedDir: (await getExternalStorageDirectory()).path,
                showNotification: true, // show download progress in status bar (for Android)
                openFileFromNotification: true, // click on notification to open downloaded file (for Android)
              );
            ,
          ))
        ])),
      ),
    );
  

在这里,如您所见,我还使用path_provider 插件来获取我要保存文件的文件夹。

【讨论】:

【参考方案2】:

如果您是 html 页面的所有者,您可以查看适合我的解决方法。在您的 html 页面 的源代码中,为特定资源链接添加 onclick 功能:

function downloadpdf() 
      var currentHref = window.location.href;
      window.history.pushState(null, null, '/app/somepdf.pdf');
      setTimeout(() => window.location.replace(currentHref), 1000);

在 Flutter 代码中添加监听器:

StreamSubscription<String> _onWebViewUrlChanged;
_onWebViewUrlChanged =
    FlutterWebviewPlugin().onUrlChanged.listen((String url) 
      if (url.contains('.pdf')) 
        launchURL(url);
      
);

launchURL 将在外部浏览器窗口中打开预定义的 url。所以你可以从flutter_webview_plugin下载pdf/etc。

您应该添加一些特定于应用的 js/flutter 魔法

【讨论】:

以上是关于如何在flutter中通过webview下载/创建pdf的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中通过更改主题来更改文本颜色

android中通过kotlin使用WebView

Flutter - 无法从 Webview 下载文件

如何实现在 Flutter 中通过蓝牙打印字符串?

如何在 Swift 中从 NSData 显示 PDF - 如何将 PDF 保存到文档文件夹 Swift - 如何在 Swift 中通过 WebView 从保存的 NSData 显示 PDF

currentuser 如何在flutter中通过fcm向另一个用户发送请求通知?