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,最后以流的方式写入文件。

flutter 的 in_app_web_view实现下载功能的更多相关文章

  1. iNeedle日志下载功能问题

    问题: iNeedle系统本身包含日志下载功能,主要是将web服务器中的用户访问日志按照一定条件进行筛选并下载,提供管理者分析.但是这次的测试中发现iNeedle日志下载一直会卡住,web界面显示正在 ...

  2. Safari 下用 "location.href = filePath" 实现下载功能的诡异 bug

    Safari 下的一些诡异 bug 我们已经领教一二,比如前文中说的 无痕浏览模式下使用 localStorage 的 API 就会报错.今天我们要讲的是利用 location.href = file ...

  3. location.href 实现点击下载功能

    如果页面上要实现一个点击下载的功能,传统做法是使用一个 a 标签,然后将该标签的 href 属性地址指向下载文件在服务端的地址(相对地址或者绝对地址),比如这样: 能这样实现是因为,在浏览器地址栏输入 ...

  4. php实现文件上传下载功能小结

    文件的上传与下载是项目中必不可少的模块,也是php最基础的模块之一,大多数php框架中都封装了关于上传和下载的功能,不过对于原生的上传下载还是需要了解一下的.基本思路是通过form表单post方式实现 ...

  5. JavaWeb学习记录(一)——response响应头之缓存设置与下载功能的实现

    一.HTTP中常用响应头 Location: http://www.it315.org/index.jsp Server:apache tomcat Content-Encoding: gzip Co ...

  6. JavaWeb实现文件上传下载功能实例解析

    转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...

  7. 【转】Android 服务器之SFTP服务器上传下载功能

    原文网址:http://blog.csdn.net/tanghua0809/article/details/47056327 本文主要是讲解Android服务器之SFTP服务器的上传下载功能,也是对之 ...

  8. wuzhicms字段的添加以及实现下载功能

    1.字段的添加 发布内容--> 栏目管理--> 字段管理-->添加字段 下面根据需求进行相应的设置. 然后提交即可. 2.下载功能的实现 实例说明: 会员中心相关页面下载功能的实现 ...

  9. windows下实现uboot的tftp下载功能

    一.原理分析 带有uboot的开发板实际上充当的就是tftp客户端,而PC机扮演的角色就是tftp服务器端,而tftp下载功能实际上就是文件传输.tftp服务器可以建立在虚拟机linux下,也可以建立 ...

  10. 用Hopper搞定Mac迅雷的会员以及离线下载功能

    转自 用Hopper搞定Mac迅雷的会员以及离线下载功能 先定位Mac迅雷的可执行文件 snakeninnys-iMac:~ snakeninny$ ls /Applications/Thunder. ...

随机推荐

  1. Solon v2.2.6 发布,助力信创国产化

    Solon 是一个高效的 Java 应用开发框架:更快.更小.更简单.它是一个有自己接口标准规范的开放生态,可为应用软件国产化提供支持,助力信创建设. 150来个生态插件,覆盖各种不同的应用开发场景: ...

  2. 企业什么喜欢做电视看板,电视看板浏览网页的必备工具 电视看板浏览器 电视看板自动打开网页 电视看板必备APP

    企业喜欢做电视看板主要是因为它可以提供以下几个方面的优势: 增强企业形象:电视看板可以将企业的信息和广告以更加生动.直观的方式呈现出来,提高企业形象和知名度. 提高工作效率:电视看板可以在企业内部作为 ...

  3. kubernetes核心实战(五)--- StatefulSets

    7.StatefulSets StatefulSet 是用来管理有状态应用的工作负载 API 对象. StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod ...

  4. wpf CommunityToolkit.Mvvm8.1 MVVM工具包安装引用指南

    CommunityToolkit.Mvvm包(又名MVVM 工具包,以前名为 Microsoft.Toolkit.Mvvm)是一个现代.快速且模块化的 MVVM 库.它支持:.NET Standard ...

  5. extend笔记

    JavaScript面向对象 继承extend 1. 概念(主要用途) 将子类中的共性代码 ( 属性和方法 ) 抽取出来 放到父类中 每当有一个新的子类需要用到共性的属性或者方法时 不需要在自己内容复 ...

  6. 【踩坑】.NET异步方法不标记async,Task<int> 返回值 return default问题

    ​ 在.NET中,返回类型为 Task<T> 的方法并不一定要标记为 async.这是因为 async 关键字只是用来告诉编译器该方法中包含异步操作,并且可以使用 await 和其他异步特 ...

  7. 一文讲透产品经理如何用好ChatGPT

    作者:京东零售 何雨航 "4.0版本的ChatGPT可以有效提升产品经理工作效率,但并无法替代产品经理的角色." 一.引言 3月15日,OpenAI发布了最新的基于GPT-4的Ch ...

  8. 深度学习03-(图像梯度处理、图像轮廓、图像预处理在AI中的应用)

    深度学习03-计算机视觉基本理论2 深度学习03-(计算机视觉基本理论2) 图像梯度处理 什么是图像梯度 模板运算 均值滤波 高斯滤波 中值滤波 边沿检测 锐化 图像轮廓 什么是图像轮廓 查找和绘制轮 ...

  9. Python-趣味小程序

    1.效果 2.代码 import sys import time def print_act(word): #print('\n'+' '+'\r') #让光标回到行首 sys.stdout.writ ...

  10. 批x网,登录加密(通过元素绑定的监听事件来找到加密函数)

    网站 base64加密 aHR0cHM6Ly93d3cucGlnYWkub3JnLw== 逆向分析 https://blog.csdn.net/a_123_4/article/details/1208 ...