Flutter WebView blob pdf 下载

Flutter WebView blob pdf download

我正在尝试使用 flutter 从网站下载文件,我首先使用 evaluateJavaScript 并在单击生成按钮之前更改了一些值,该按钮应该将适当的 pdf 文件下载到 phone。

这是我的代码:

InAppWebView(
        initialUrl: '...',
        initialOptions: InAppWebViewGroupOptions(
          crossPlatform: InAppWebViewOptions(
              debuggingEnabled: true,
              useOnDownloadStart: true,
              javaScriptEnabled: true,
          ),
        ),
        //javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (InAppWebViewController webViewController) {
          _controller = webViewController;
          },
          onLoadStop: (_controller ,url) async {
          await _loadData();

          _controller.evaluateJavascript(source:
"console.log(document.getElementById('field-lastname').value = '${data[Field.name]}' );"
+"console.log(document.getElementById('generate-btn').click());"

           );
          },

          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,);
          },

      ),

打印出来的URL是这样的

onDownloadStart blob:https://example.com/a2a5316c-9290-4da7-8a2a-9f899861046a

这是控制台:

有人可以帮助我吗?

使用 blob 下载文件 url 很棘手,并且在 Flutter 的当前 webview 状态下不支持开箱即用。有 3 个流行的插件

社区存储库中的自述文件中有注释

We are working closely with the Flutter Team to integrate all the Community Plugin features in the Official WebView Plugin. We will try our best to resolve PRs and Bugfixes, but our priority right now is to merge our two code-bases. Once the merge is complete we will deprecate the Community Plugin in favor of the Official one

要构建完全可用且无错误的 webview,还有很多工作要做。目前,对于此处提到的更具挑战性的任务,最好的尝试是使用 flutter_inappwebview,它非常流行并被很多人成功使用。 There is issue associated with blob files. As we can see in your snippet you already used this plugin. To download blob file you can try convert blob:url to base64 like in this case Download Blob file from Website inside Android WebViewClient

可能的解决方法

在您的网络视图 (_controller) 中添加 JavaScriptHandler。我假设 onWebViewCreated 可能没问题。

        controller.addJavaScriptHandler(
          handlerName: _webViewHandlerName,
          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 yourExtension =
                  _mapMimeTypeToYourExtension(receivedMimeType); // 'pdf'

              _createFileFromBase64(
                  receivedFileInBase64, 'YourFileName', yourExtension);
            }
          },
        );

JavaScript 处理程序将接收存储在数组中的两个值。第一个参数是以 base64 编码的文件,第二个参数是 mimeType,例如application/pdf。拥有关于 mimeType 的信息允许我们获得关于应该用于保存文件的扩展名的信息。 它们可以很容易地映射 application/pdf => 'pdf' 等

  _createFileFromBase64(String base64content, String fileName, String yourExtension) async {
    var bytes = base64Decode(base64content.replaceAll('\n', ''));
    final output = await getExternalStorageDirectory();
    final file = File("${output.path}/$fileName.$yourExtension");
    await file.writeAsBytes(bytes.buffer.asUint8List());
    print("${output.path}/${fileName}.$yourExtension");
    await OpenFile.open("${output.path}/$fileName.$yourExtension");
    setState(() {});
  }

最后在可以处理 blob url 的地方调用 JavaScript。

       onDownloadStart: (controller, url) async {
        print("onDownloadStart $url");
        var jsContent = await rootBundle.loadString("assets/js/base64.js");
        await controller.evaluateJavascript(
            source: jsContent.replaceAll("blobUrlPlaceholder", url));
      },

Javascript(我更喜欢将其作为资产加载 base64.js,比在 dart 代码中硬编码更好) 它打开 blob url 并将 encodedBase64 数据和 mimeType 作为参数传递给我们在 dart 中的处理程序 blobToBase64Handler

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();

来源:Download Blob file from Website inside Android WebViewClient

来源:How to decode base64 PDF string in Flutter?

它不干净,看起来很破旧,但找不到更好更简单的东西

我为 Android 和 iOS 写了一个解决方案。可能支持任何类型的文件。

  1. 使用 Fluter 和 Jaguar 或其他后端框架构建一个简单的后端
  2. 将 blob 转换为 formData 并将其post 转换为 Flutter。

完整代码:https://github.com/guoguoguilai/flutter-webview-blob-download