Flutter Web中如何在浏览器中打开已下载的文件?
Flutter Web 下载带认证Token的文件后在新标签页打开的解决方案
由于Flutter Web没有原生临时目录,且目标文件需要携带认证Token才能请求、无法直接通过URL访问,我们可以通过Blob + Object URL的方式在内存中处理文件数据,实现新标签页打开的需求。
具体实现步骤
- 导入
dart:html包(仅Web平台生效,借助kIsWeb做平台判断) - 将下载得到的字节数据转换为浏览器可识别的Blob对象
- 基于Blob生成临时Object URL
- 在新标签页打开该URL,最后释放URL避免内存泄漏
修改后的下载函数
import 'dart:html' as html; // 其他必要导入(如http、path_provider等)... Future<XFile?> download({required String path, Map<String, dynamic>? queryParams}) async { Options options = generateOptions(await generateToken(), responseType: ResponseType.bytes); Map<String, String> headers = {}; options.headers?.forEach((key, value) { headers[key] = '$value'; }); try { var response = await http.get( Uri.parse(path), headers: headers, ); // 处理MIME类型,为空时用通用二进制类型兜底 String mimeType = response.headers['content-type'] ?? 'application/octet-stream'; // 从响应头提取文件名,无则用默认值 String fileName = response.headers['content-disposition']?.split('filename=').last ?? 'File'; String filePath = '${kIsWeb == true ? fileName : (await getTemporaryDirectory()).path}/$fileName'; XFile file = XFile.fromData( response.bodyBytes, mimeType: mimeType, name: fileName, path: filePath, ); if (!kIsWeb) { await File(filePath).create(recursive: true); await File(filePath).writeAsBytes(await file.readAsBytes()); } else { // Web端核心逻辑:生成Blob并在新标签页打开 final blob = html.Blob([response.bodyBytes], mimeType); final url = html.Url.createObjectUrlFromBlob(blob); // 新标签页打开文件 html.window.open(url, '_blank'); // 释放临时URL,防止内存泄漏 html.Url.revokeObjectUrl(url); // 若需要同时保留下载功能,取消注释下面一行 // await WebDownloader.downloadBase64(base64data: base64Encode(response.bodyBytes), filename: fileName); } return file; } catch (e) { errorManagement(e); } return null; }
关键注意事项
- MIME类型适配:如果响应头未返回
content-type,可根据文件名后缀手动指定(如.pdf对应application/pdf),提升浏览器对文件的识别准确性。 - 内存泄漏防范:必须调用
html.Url.revokeObjectUrl(url)释放临时URL,避免长期运行导致浏览器内存占用过高。 - 跨平台兼容:通过
kIsWeb判断平台,确保dart:html相关代码仅在Web环境执行,不影响Android/iOS端编译运行。
内容的提问来源于stack exchange,提问作者Pandruz
相关产品推荐
相关产品推荐

