You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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处理

该方案适配现有交互逻辑,改动量最小:

  1. 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);
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 17:57:02