如何通过URL直接下载图片而非在新标签页中打开
解决方案(适配Flutter Web场景)
方案1:同源图片资源直接下载
无需额外请求资源,直接通过浏览器锚点API触发下载:
import 'dart:html' as html; void downloadImage(String imageUrl, String saveFileName) { final anchor = html.AnchorElement(href: imageUrl) ..setAttribute('download', saveFileName) ..target = '_self'; html.document.body?.append(anchor); anchor.click(); anchor.remove(); }
方案2:跨域图片资源流下载
先以二进制流形式拉取资源,再触发浏览器下载,不会打开新标签页:
import 'dart:html' as html; import 'package:dio/dio.dart'; Future<void> downloadNetworkImage(String imageUrl, String saveFileName) async { // 以blob流形式请求资源,不会触发页面跳转 final response = await Dio().get( imageUrl, options: Options(responseType: ResponseType.blob), ); final blob = html.Blob([response.data]); final tempUrl = html.Url.createObjectUrlFromBlob(blob); // 触发下载 final anchor = html.AnchorElement(href: tempUrl) ..setAttribute('download', saveFileName) ..target = '_self'; html.document.body?.append(anchor); anchor.click(); // 清理临时资源避免内存泄漏 html.Url.revokeObjectUrl(tempUrl); anchor.remove(); }
原有方案失效原因说明
url_launcher/url_launcher_web的默认逻辑是调用浏览器访问目标链接,如果服务端未返回Content-Disposition: attachment响应头,浏览器会直接预览图片而非下载,还会触发新标签页打开- 原有dio写法是桌面/移动端的文件写入逻辑,Web端没有直接写入本地文件系统的权限,需要走浏览器原生下载机制实现
注意事项
如果是跨域资源,需要资源所在的服务端配置CORS规则,允许你的站点域名请求资源,否则会触发跨域拦截无法拉取blob流。
内容的提问来源于stack exchange,提问作者NM Naufaldo
相关产品推荐
相关产品推荐

