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

Flutter Web公网图片可展示但下载报XMLHttpRequest错误求生产环境方案

Flutter Web生产环境图片下载XMLHttpRequest错误解决方案

问题描述

Flutter Web环境中,公网图片可正常展示,但点击下载时触发如下错误:

Error: XMLHttpRequest error. dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 299:10  createErrorWithStack dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 355:28            _throw dart-sdk/lib/core/errors.dart 120:5                                           throwWithStackTrace dart-sdk/lib/async/zone.dart 1385:11                                          callback dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>

当前使用image_downloader_web: ^2.0.2插件,Web端下载代码如下:

if (kIsWeb) {
  await WebImageDownloader.downloadImageFromWeb(
    "$image_url",
    imageQuality: 100,
    name: 'image',
  );
} 

仅修改Flutter文件只能在测试环境实现图片下载,现寻求生产环境可用的解决方案。另外,Android端使用以下代码可正常下载该图片:

var response = await Dio().get(
  "$image",
  options: Options(responseType: ResponseType.bytes)
);
final result = await ImageGallerySaver.saveImage(
  Uint8List.fromList(response.data),
  quality: 100,
  name:"image"
);

解决方案

方案1:浏览器原生API实现下载(绕过CORS限制)

直接用浏览器a标签逻辑完成下载,避免插件的XMLHttpRequest跨域限制,和Android端逻辑统一,生产环境稳定:

import 'dart:html' as html;
import 'dart:typed_data';
import 'package:dio/dio.dart';

Future<void> downloadImageWeb(String imageUrl) async {
  // 用Dio获取图片字节数据
  final response = await Dio().get(
    imageUrl,
    options: Options(responseType: ResponseType.bytes),
  );
  final Uint8List bytes = response.data;

  // 转换为Blob对象并生成临时URL
  final html.Blob blob = html.Blob([bytes]);
  final String url = html.Url.createObjectUrlFromBlob(blob);

  // 创建隐藏a标签触发下载
  final html.AnchorElement anchor = html.AnchorElement(href: url)
    ..setAttribute("download", "image.jpg")
    ..style.display = "none";
  html.document.body?.children.add(anchor);
  anchor.click();

  // 清理资源
  html.document.body?.children.remove(anchor);
  html.Url.revokeObjectUrl(url);
}

方案2:配置服务器CORS策略

如果能控制图片所在服务器,添加以下CORS响应头,允许你的Web域名跨域访问:

  • Access-Control-Allow-Origin: 你的Web域名(生产环境避免用*)
  • Access-Control-Allow-Methods: GET, HEAD
  • Access-Control-Allow-Headers: Range

配置完成后,原插件的下载代码可直接在生产环境使用。

方案3:代理服务器中转请求

无法修改目标服务器时,搭建代理服务器转发图片请求,同时配置代理服务器允许跨域:
示例Node.js代理代码:

const express = require('express');
const axios = require('axios');
const app = express();

app.get('/proxy-image', async (req, res) => {
  const imageUrl = req.query.url;
  try {
    const response = await axios.get(imageUrl, { responseType: 'stream' });
    res.setHeader('Access-Control-Allow-Origin', '你的Web域名');
    response.data.pipe(res);
  } catch (err) {
    res.status(500).send('下载失败');
  }
});

app.listen(3000, () => console.log('代理服务器运行在3000端口'));

客户端修改为请求代理地址:

await WebImageDownloader.downloadImageFromWeb(
  "http://你的代理服务器地址/proxy-image?url=$image_url",
  imageQuality: 100,
  name: 'image',
);

方案选择建议

  • 优先选方案1:无需服务器改动,客户端独立实现,适配性强
  • 能控制服务器选方案2:代码无改动,最简洁
  • 无法控制服务器选方案3:适合依赖原插件功能的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:57:21