首页 > 其他分享 >flutter 的 in_app_web_view实现下载功能

flutter 的 in_app_web_view实现下载功能

时间:2023-06-07 16:35:39浏览次数:56  
标签:case web String extension app break blob flutter

flutter与前端交互,利用in_app_web_view实现下载功能:

首先下载库,终端输入

flutter pub add flutter_inappwebview

之后导出

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

即可使用。

创建in_app_web_view:

InAppWebView(
     initialOptions:
          InAppWebViewGroupOptions(
              crossPlatform:InAppWebViewOptions(
                useOnDownloadStart:true,
              ),
              android: AndroidInAppWebViewOptions()
          ),
      //老版本:initialUrl    新版本:initialUrlRequest
      initialUrlRequest: URLRequest(
        url: Uri.parse(widget.url),
      )
)

因为要下载文件,所以请务必手动设置 useOnDownloadStart 为 true(否则出发文件下载的监听)。

initialUrlRequest中可填写自己想首先打开的url地址。

可参考例子:flutter_inappwebview_examples/main.dart at main · pichillilorenzo/flutter_inappwebview_examples · GitHub

https://github.com/pichillilorenzo/flutter_inappwebview_examples/blob/main/file_download/lib/main.dart

填写自己需要的回调(例子中的一点错误,没有开启 useOnDownloadStart, 因此不会下载成功,在使用时请设置为true)

正常情况下,配合downloader和android_path_provider,普通https链接即可下载文件。

 

而遇到blob链接时,还需要进行更多操作来确保文件的下载:

可参考javascript - Flutter WebView blob pdf download - Stack Overflow

https://stackoverflow.com/questions/64865972/flutter-webview-blob-pdf-download/64902313#64902313

因为Android不支持blob链接下载,因此我们嵌套javascript处理下载链接,在in_app_web_view的build中重写onWebViewCreated方法,添加javascriptHandler:

onWebViewCreated: (InAppWebViewController controller) {
        if (mounted) {
          setState(() {
            _inAppWebCtrl = controller;
            _inAppWebCtrl!.addJavaScriptHandler(
              handlerName: 'blobToBase64Handler',
              callback: (data) async {
                if (data.isNotEmpty) {
                  final String receivedFileInBase64 = data[0];
                  final String receivedMimeType = data[1];

                  // NOTE: create a method that will handle your extensions
                  final String extension =
                  _mapMimeTypeToExtension(receivedMimeType);
                  String tmpFileName = 'tmpfile';
                  _createFileFromBase64(
                      receivedFileInBase64, tmpFileName, extension);
                }
              },
            );
          });
        }
      },

首先在assets中添加js文件夹,然后创建 base64.js 文件

var xhr = new XMLHttpRequest();
var blobUrl = "blobUrlPlaceholder";
console.log(blobUrl);
xhr.open('GET', blobUrl, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  if (this.status == 200) {
    var blob = this.response;
    var reader = new FileReader();
    reader.readAsDataURL(blob);
    reader.onloadend = function() {
      var base64data = reader.result;
      var base64ContentArray = base64data.split(",");
      var mimeType = base64ContentArray[0].match(/[^:\s*]\w+\/[\w-+\d.]+(?=[;| ])/)[0];
      var decodedFile = base64ContentArray[1];
      console.log(mimeType);
      window.flutter_inappwebview.callHandler('blobToBase64Handler', decodedFile, mimeType);
    };
  };
};
xhr.send();

 

注意js中的callhander的名字参数,对应创建webview时addJavascriptHandler中的name。

另外是文件类型映射函数和文件下载函数:

  String _mapMimeTypeToExtension(String mimeType) {
    String extension = '';
    switch(mimeType) {
      case 'image/png': extension = 'png'; break;
      case 'application/msword': extension = 'doc'; break;
      case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
        extension = 'docx';
        break;
      case 'image/jpeg': extension = 'jpg'; break;
      case 'image/gif': extension = 'gif'; break;
      case 'image/svg+xml': extension = 'svg'; break;
      case 'image/tiff': extension = 'tif'; break;
      case 'text/plain': extension = 'txt'; break;
      case 'application/vnd.ms-powerpoint': extension = 'ppt'; break;
      case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
        extension = 'pptx';
        break;
      case 'application/vnd.ms-excel': extension = 'xls'; break;
      case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
        extension = 'xlsx';
        break;
      case 'application/zip': extension = 'zip'; break;
      case 'application/x-7z-compressed': extension = '7z'; break;
      case 'application/pdf': extension = 'pdf'; break;
    }
    return extension;
  }

  _createFileFromBase64(String base64content, String fileName, String yourExtension) async {
    var bytes = base64Decode(base64content.replaceAll('\n', ''));
    final file = File("$_localPath/$fileName.$yourExtension");
    await file.writeAsBytes(bytes.buffer.asUint8List());
    
  }

最后重写inappwebview中的下载请求方法:

      onDownloadStartRequest: (controller, downloadStartRequest) async {
          var jsContent = await rootBundle.loadString("assets/js/base64.js");
// 运行javascript代码解析blob
          await controller.evaluateJavascript(
              source: jsContent.replaceAll("blobUrlPlaceholder",
                  downloadStartRequest.url.toString()));
      },

总结:因为android本身不能解析blob,我们因此使用javascript作为翻译:运行顺序:

onDownloadStartRequest -> javascript文件 -> webviewController中的handler的callback,最后以流的方式写入文件。

 

标签:case,web,String,extension,app,break,blob,flutter
From: https://www.cnblogs.com/jiang448/p/17463750.html

相关文章

  • uniapp render.js
    1、操作数据<template><viewclass="content"><view@click="renderScript.emitData">获取renderjs数据</view>{{name}}</view></template><script>exportdefault{data(){......
  • app默认开机自启动/不自启动
    需求:将应用添加到应用白名单,应用开机后将会在后台自启动,黑名单则相反修改内容:将对应apk包名添加到黑/白名单array数组当中修改文档:vendor/mediatek/proprietary/packages/apps/DuraSpeed/res/values/config.xml 其它内部逻辑代码:vendor/mediatek/proprietary/packages/apps......
  • -webkit-line-clamp 设置行数限制
    设定文字最多现实两行,超出后...display:-webkit-box;必须结合的属性,将对象作为弹性伸缩盒子模型显示。-webkit-box-orient必须结合的属性,设置或检索伸缩盒对象的子元素的排列方式。text-overflow,可以用来多行文本的情况下,用省略号“...”隐藏超出范围的  ove......
  • 顶象发布《车企App安全研究白皮书》,剖析品牌汽车App的两大类风险
    近日,顶象发布《车企App安全研究白皮书》。该白皮书总结了当前车企App主要面临的技术威胁和合规风险,详细分析了风险产生的原因,并提出相应安全解决方案。车企App成汽车品牌首选自有App成为各品牌汽车的标配,也成为车企必争的新战场。车企App不仅能够实现远程开启空调、门锁、启动......
  • 直播app开发搭建,web前端JS中的继承方式
    直播app开发搭建,web前端JS中的继承方式ES5//ES5中的写法一   functionPhone(color){    this.color=color;    this.show=function(){      console.log("你喜欢看的颜色是:"+this.color);    }  }  functionVivo(color......
  • app直播源码,HTML的导航栏的代码
    app直播源码,HTML的导航栏的代码<!DOCTYPEhtml><html><head>  <metacharset="UTF-8">  <title>导航栏</title>  <style>    .box{      height:40px;      border-top:3pxsolidred;      border-bot......
  • uniapp离线打包总结
    uniapp离线打包总结一、准备好AndroidStudio的项目外壳,这里采用的是https://nativesupport.dcloud.net.cn/AppDocs/download/android.html#下载后选用HBbuilder-Integrate-AS作为外壳,如下图所示二、Android模块配置按项目所用到的模块进行配置,详情参考官网https://nativesu......
  • 【Web IDE】code-server搭建记录
    起因最近因为越来越多极其繁琐的专业课,而我的游戏本我实在是背不动了。。。所以想在云端为iPad搭建一个开发环境,一个是解放一下自己的书包,一个是让自己的服务器发挥点作用。。环境TencentCloudUbuntu20.04LTS1H2G+1M搭建安装docker一类的就不再赘述了,完成上述步骤后,直接安装cod......
  • 一次有关 DNS 解析导致 APP 慢的问题探究
    目录一、业务背景二、问题三、问题排查3.1、问题一:基于DNS延迟的解析3.2、问题二:HTTPDNS侧HTTPDNS基础理论相关问题四、优化方向4.1、域名解析配置4.2、靠近HTTPDNS服务端层4.3、靠近用户层五、扩展5.1、如何测试本地到权威DNS服务器获取域名的时间5.2、同地区不同网络,访问......
  • .net core WebAPI 初探及连接MySQL
    1.前言笔者最近跟着微软官方文档学习.netcoreWebAPI,但发现其对WebAPI连接数据库、读取数据库方面讲得不够细致明了。写此文的目的,即实现.netcoreWebAPI的GET、POST方法访问数据库,并输出结果。2.开发准备2.1操作系统Windows10/Windows72.2.netcoresdk.netcore......