当前位置: 首页 >  资讯 >  >  详情
【环球新要闻】flutter 的 in_app_web_view实现下载功能
2023-06-07 18:05:11    来源:博客园

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

关键词:

上一篇:海昌海洋公园(02255)称不知股价异动原因|世界资讯
下一篇:最后一页