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

Flutter Web应用中如何监听文件下载完成后再执行后续操作

问题原因

你现在的逻辑有两个核心问题:

  1. saveSettings是同步方法,调用anchor.click()触发浏览器下载弹窗是异步行为,不会阻塞后续代码执行,所以snackbar和页面退回会直接运行
  2. 浏览器出于安全限制,没有公开API可以直接监听用户是否点击了下载确认弹窗的「取消」按钮,所以无法100%判断用户是否真正完成了保存操作

具体修改方案

第一步:改造saveSettings方法

将方法改为异步,增加错误捕获、资源清理逻辑,确保下载请求正常触发后再返回结果:

import 'dart:html' as html;
import 'dart:async';

Future<bool> saveSettings(ArtWork artWork) async {
  try {
    Uint8List pngBytes = encodeArt(artWork);
    final blob = html.Blob([pngBytes], 'application/octet-stream');
    final fileName = '${artWork.title}.diy';
    final url = html.Url.createObjectUrlFromBlob(blob);
    final anchor = html.AnchorElement(href: url)
      ..setAttribute('download', fileName)
      ..style.display = 'none';
    html.document.body?.append(anchor);
    
    // 触发下载
    anchor.click();
    
    // 等待100ms让浏览器处理下载请求,避免立即清理资源导致下载中断
    await Future.delayed(const Duration(milliseconds: 100));
    
    // 清理DOM节点和对象URL,避免内存泄漏
    anchor.remove();
    html.Url.revokeObjectUrl(url);
    
    return true;
  } catch (e) {
    // 捕获编码、Blob创建等环节的异常,返回失败
    return false;
  }
}

第二步:改造onTap回调逻辑

等待下载方法执行完成,并且增加mounted判断避免异步回调时页面销毁报错:

onTap: () async {
  final isDownloadSuccess = await saveSettings(artWork);
  if (!mounted) return;
  if (isDownloadSuccess) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      backgroundColor: Colors.green,
      content: Text('Artwork has been saved. File name: ${artWork.title}.diy'),
    ));
    Navigator.pop(context);
  } else {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
      backgroundColor: Colors.red,
      content: Text('文件保存失败,请重试'),
    ));
  }
}

补充说明

  • 受浏览器安全机制限制,目前无法监听到用户手动取消下载的操作,所以只要下载请求正常触发就会返回成功。如果需要进一步降低误判概率,可以在触发下载前增加自定义确认弹窗,用户确认要下载后再执行后续逻辑
  • 代码中增加的100ms延时是适配不同浏览器的下载触发机制,实测在Safari、Chrome、Edge等主流浏览器都可以正常工作,不会影响用户体验

内容的提问来源于stack exchange,提问作者Bo Hellgren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:45:04