flutter與前端交互,利用in_app_web_view實現(xiàn)下載功能:
首先下載庫,終端輸入
flutter pub add flutter_inappwebview
之后導出
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
即可使用。
創(chuàng)建in_app_web_view:
InAppWebView( initialOptions: InAppWebViewGroupOptions( crossPlatform:InAppWebViewOptions( useOnDownloadStart:true, ), android: AndroidInAppWebViewOptions() ), //老版本:initialUrl 新版本:initialUrlRequest initialUrlRequest: URLRequest( url: Uri.parse(widget.url), ) )
因為要下載文件,所以請務必手動設置?useOnDownloadStart 為 true(否則出發(fā)文件下載的監(jiān)聽)。
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
填寫自己需要的回調(diào)(例子中的一點錯誤,沒有開啟 useOnDownloadStart, 因此不會下載成功,在使用時請設置為true)
正常情況下,配合downloader和android_path_provider,普通https鏈接即可下載文件。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-474535.html
而遇到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文件夾,然后創(chuàng)建 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的名字參數(shù),對應創(chuàng)建webview時addJavascriptHandler中的name。
另外是文件類型映射函數(shù)和文件下載函數(shù):
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())); },
總結(jié):因為android本身不能解析blob,我們因此使用javascript作為翻譯:運行順序:
onDownloadStartRequest -> javascript文件 -> webviewController中的handler的callback,最后以流的方式寫入文件。文章來源:http://www.zghlxwxcb.cn/news/detail-474535.html
?
到了這里,關于flutter 的 in_app_web_view實現(xiàn)下載功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!