Flutter web 无法从其他域加载网络图片。

97

1
请尝试阅读此处的文档:https://flutter.dev/docs/development/platform-integration/web-images#cross-origin-images - ddalbosco
我尝试过,但我无法跟进。 - Abel Ayalew
1
你能展示一下你使用网络图片的代码吗? - Farrukh Sajjad
1
尝试使用这个包“image_network 2.5.1”,它可以在任何平台上正常工作。 - Aqeel Mughal
17个回答

129
为了能够在Flutter网页上显示来自任何其他域名或Firebase存储的图像,您需要配置CORS数据:
  1. Open the GCP console, select your project and start a cloud terminal session by clicking the >_ icon button in the top navbar.

  2. Click the open editor button (pencil icon), then create the cors.json file. The cors.json file should look like this:

    [
      {
        "origin": ["*"],
        "method": ["GET"],
        "maxAgeSeconds": 3600
      }
    ]
    

    I set the origin to * which means that every website can display your images. But you can also insert the domain of your website there to restrict access.

  3. Run gsutil cors set cors.json gs://your-bucket


如果您需要更多信息:https://cloud.google.com/storage/docs/configuring-cors


14
第二步,要创建cors.json文件,请点击与Explorer:XXXX同一行的3个点(...),或者只需点击“文件>新建文件”。第三步:在Firebase储存控制台中找到“your-bucket”,当您运行shell命令时,您将需要进行授权。 - theSpuka
9
验证:gsutil cors get gs://your-bucket - Liel van der Hoeven
3
在尝试了上述所有建议后,我的Flutter Web应用仍无法工作。我正在尝试在应用中显示YouTube缩略图。在第3步之后是否有任何遗漏?是否需要执行任何重新加载或刷新命令?请给我建议。 - Raghu Mudem
这似乎只是与Firebase和Google Cloud相关的配置。在Flutter应用程序中是否还涉及其他配置?因为图片仍然无法加载并抛出缺少CORS标头错误。 - sh_ark
3
对于像我这样对存储桶一无所知且遭遇403错误的人,你可以通过gsutil ls命令获取你的存储桶列表,并检查哪一个被你的应用程序使用,然后为该存储桶设置cors.json文件,以解决问题。 - Ali Azimoshan
显示剩余6条评论

92

解决此问题有两种方法,一种是使用HTML渲染器运行您的应用程序,另一种是设置CORS配置。

1. 使用HTML渲染器

从文档中获取

CORS是浏览器用来控制一个站点如何访问另一个站点资源的机制。默认情况下,一个网站不被允许使用XHR或fetch向另一个站点发出HTTP请求。这样可以防止另一个站点上的脚本代表用户执行操作并未经许可访问另一个站点的资源。

当使用<img>、<picture>或<canvas>时,浏览器在知道图像来自另一个站点并且CORS策略禁止访问数据时会自动阻止对像素的访问。

Flutter在Web上有两个渲染器,canvaskit和html。当您在Flutter Web上运行/构建应用程序时,它会根据运行的设备使用相应的渲染器。

HTML渲染器:适用于在移动浏览器中运行的应用程序。

CanvasKit渲染器:适用于在桌面浏览器中运行的应用程序。

自动(默认) - 自动选择要使用的渲染器。

HTML 渲染器可以在没有额外配置的情况下加载跨域图像,因此您可以使用以下命令来运行和构建应用程序。

flutter run -d chrome --web-renderer html // to run the app

flutter build web --web-renderer html --release // to generate a production build

来源: https://docs.flutter.dev/development/tools/web-renderers

2. 设置CORS配置

  • 下载包含一个名为gsutil的工具的Google-cloud-sdk
  • 在您的Flutter项目中创建一个名为cors.json的文件,并添加以下JSON内容,这将删除所有域限制。(无论此文件位于何处)
[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]

运行gcloud init(位于google-cloud-sdk/bin)。 通过点击链接进行身份验证,并在控制台中选择项目。 最后执行gsutil cors set cors.json gs://<your-bucket-name>.appspot.com。您可以在Firebase存储中找到您的存储桶名称。 我已经在github gists中记录了整个过程。

在您的文件树中,您应该把 cors.json 文件放在哪里?(这有关系吗?) - Yves Boutellier
一旦运行gsutil命令,cors.json就不再重要了。 - Mahesh Jamdade
@InderPalSingh,一旦我们通过运行最后一个命令上传配置,就不再需要cors.json文件了。 - Mahesh Jamdade
谢谢。在最后一步(解决方案2)中出现了错误:CommandException:“cors”命令跨提供程序不允许。-有任何想法如何修复? - Kdon
@MaheshJamdade,是的,我有这个文件,但意识到需要从项目目录中运行命令。现在运行良好,谢谢。 - Kdon
显示剩余3条评论

52

我通过使用HTML渲染器解决了这个问题:

flutter build web --release --web-renderer html
或者
flutter run --web-renderer html

它适用于部署和调试。 - Abel Ayalew
Flutter Web中的Google Places API无法加载。 - IamVariable
4
这样渲染会导致图像和文字密度变得很差,请不要使用这种类型的渲染。 - Abdulmalek Dery

33

只需在您的 Flutter 代码 (web/index.html) 中添加以下内容:

<script type="text/javascript">
    window.flutterWebRenderer = "html";
</script>

这种方法的副作用是,Web 版本(至少对我来说)在项目中停止了渲染 Google 字体 :/(截至 Flutter 3.3.5)。 - Dana
但是如果我使用这个渲染器,Lottie动画就无法工作。 - Balaji

30

对我来说,这个方法有效:

flutter run -d chrome --web-renderer html

2
参数在部署时起作用。在构建期间只需要添加相同的参数 flutter build web --web-renderer html 即可。 - Omatt
@Omatt https://dev59.com/ne3qx4gBAO4CwREcDhHf#76413900 - Rehan

22

如果您使用Firebase存储,请按照以下步骤操作:

  1. 在您的项目中打开Google Cloud控制台

  2. 点击右上角的控制台图标。

  3. 点击“打开编辑器”。

  4. 点击“文件 > 新建 > cors.json”。

  5. 粘贴下面的代码:

[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]
  • 然后在控制台中运行:

    gsutil cors set cors.json gs://bucket-name
    

    bucket-name是存储桶的名称,您可以在Firebase项目中的存储部分文件夹上方找到它。


  • 请执行以下命令以验证:'gsutil cors get gs://your-bucket' - Leonardo Rignanese

    11
    为了快速调试,可以通过在运行配置中添加参数--web-renderer html,而不是从终端运行flutter run -d chrome --web-renderer html。在菜单栏中,通过Run > Edit Configurations进行导航。

    运行配置


    7

    这应该是被接受的答案。 - Joran

    6

    如果您无法更新CORS设置或添加代理,请选择CanvasKit(性能更好)而不是HTML渲染器 - 可以使用平台视图显示图像:

    import 'dart:html';
    import 'package:flutter/material.dart';
    import 'dart:ui' as ui;
    
    class MyImage extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        String imageUrl = "image_url";
        // https://github.com/flutter/flutter/issues/41563
        // ignore: undefined_prefixed_name
        ui.platformViewRegistry.registerViewFactory(
          imageUrl,
          (int _) => ImageElement()..src = imageUrl,
        );
        return HtmlElementView(
          viewType: imageUrl,
        );
      }
    }
    
    
    

    2
    我想给图像小部件添加适应属性,你有什么好的想法怎样添加呢? - kishan vekariya

    3

    运行中

    flutter run --web-renderer html
    

    解决了我的问题。


    每次在Flutter中复制更改时都会执行此命令,该命令可以正常工作,但重新执行更改后不再起作用。 - Lenin Zapata

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接