Flutter中url_launcher无法打开webview传递的blob URL是什么原因?
问题原因
blob: 格式的URL是Web运行时的临时内存资源标识,仅在创建它的WebView上下文内有效,Flutter原生侧的url_launcher无法访问WebView内存中的临时资源。此外blob并不是iOS系统可识别的通用URL Scheme,即便在info.plist中添加了白名单配置,系统也找不到可以处理该类URL的应用,因此会抛出OSStatus error -10814错误。
可行解决方案
方案1:Web端转Base64传输给Flutter处理
该方案适配现有交互逻辑,改动量最小:
- Web端修改逻辑,不再传递blob URL,改为将PDF Blob转成Base64字符串后传给Flutter:
let pdf = await Api.getReceiptAsPdf(receipt.id); var file = new Blob([pdf], {type: 'application/pdf'}); if (isFlutterApp) { // Blob转Base64 const reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { const base64Pdf = reader.result; sendFlutterNotification(base64Pdf); } } else { var fileURL = URL.createObjectURL(file); window.open(fileURL); }
- Flutter侧新增Base64转本地临时文件逻辑,再调用
url_launcher打开本地文件:
首先需要在pubspec.yaml中添加path_provider依赖用于获取系统临时目录,对应代码如下:
import 'dart:io'; import 'dart:convert'; import 'package:path_provider/path_provider.dart'; import 'package:url_launcher/url_launcher.dart'; void _openPdfFromBase64(String base64Pdf) async { // 移除Base64前缀标识 final pureBase64 = base64Pdf.split(',').last; final pdfBytes = base64Decode(pureBase64); // 写入本地临时文件 final tempDir = await getTemporaryDirectory(); final pdfFile = File('${tempDir.path}/receipt.pdf'); await pdfFile.writeAsBytes(pdfBytes); // 打开本地PDF文件 final localPath = pdfFile.path; if (await canLaunch(localPath)) { await launch(localPath); } else { throw '无法打开PDF文件'; } }
方案2:直接在WebView内打开PDF
如果没有必须在原生侧打开的需求,可直接修改交互逻辑,在WebView中直接打开PDF,无需将资源抛给原生处理:
- 为WebView配置允许弹出新窗口的属性,Web端仍沿用
window.open(blobURL)逻辑即可。
方案3:后端生成临时HTTP下载链接
适合PDF体积较大的场景,避免Base64传输大字符串导致的性能损耗:
- 后端接口返回带过期时间的临时PDF下载链接(http/https格式),Web端直接将该链接传给Flutter,
url_launcher可直接打开该公网链接。
内容的提问来源于stack exchange,提问作者jola
相关产品推荐
相关产品推荐

