Flutter web can't load network image from another domain - flutter

I can't load network images in flutter web from other domains with API calls. getting this error
Trying to load an image from another domain? Find answers at:
https://flutter.dev/docs/development/platform-integration/web-images
ImageCodecException: Failed to load network image.
any help?

For being able to display your images from any other Domain or from Firebase Storage on a Flutter web page you have to configure your data for CORS.
Open the GCP console, select your project and start a cloud terminal session by clicking the >_ icon button in the top navbar.
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.
Run gsutil cors set cors.json gs://your-bucket
If you need more information: https://cloud.google.com/storage/docs/configuring-cors

There are two ways to resolve this either run your app using HTML renderer or set up the CORS configuration.
1. Using HTML renderer
Taken from the docs
CORS is a mechanism that browsers use to control how one site accesses the resources of another site. It is designed such that, by default, one web-site is not allowed to make HTTP requests to another site using XHR or fetch. This prevents scripts on another site from acting on behalf of the user and from gaining access to another site’s resources without permission
When using <img>, <picture>, or <canvas>, the browser automatically blocks access to pixels when it knows that an image is coming from another site and the CORS policy disallows access to data.
Flutter has two renderers for web, canvaskit and html
When you run/build app on the flutter web it uses renderers based on the device where its running.
HTML renderer: when the app is running in a mobile browser.
CanvasKit renderer: when the app is running in a desktop browser.
auto (default) - automatically chooses which renderer to use.
The HTML renderer can load cross-origin images without extra configuration.
so you could use these commands to run and build the app.
flutter run -d chrome --web-renderer html // to run the app
flutter build web --web-renderer html --release // to generate a production build
source: https://docs.flutter.dev/development/tools/web-renderers
2. Setup CORS Configuration
Download the Google-cloud-sdk which contains a tool called gsutil
In your flutter project create a file called cors.json and add this json file which will remove all domain restrictions.
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
Run gcloud init (located in google-cloud-sdk/bin)
Authenticate yourself by clicking the link and choose the project in the console.
finally execute gsutil cors set cors.json gs://<your-bucket-name>.appspot.com You can find your bucket name in firebase storage.
I have documented this entire process in github gists

i solve this issue by using html renderer
flutter build web --release --web-renderer html
or
flutter run --web-renderer html

for me flutter run -d chrome --web-renderer html worked.

Simply.. in your flutter (web/index.html) add this:

If you use firebase storage just follow these steps:
Open Google Cloud Console at your project
Click on console icon in top right corner
Click Open editor
Click File->New->cors.json
Place code below
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
Then Run in console
**
gsutil cors set cors.json gs://bucket-name
**
bucket-name is the name of the storage bucket which you can find on your firebase project above the folders in the storage section

Add this code in your web/index.html file
<script type="text/javascript">
window.flutterWebRenderer = "html";
</script>

To debug quickly, instead of flutter run -d chrome --web-renderer html running from the terminal you can also add the arguments --web-renderer html on your run config. On the menu bar, navigate through Run > Edit Configurations

If you can't update CORS settings or add proxy, prefer CanvasKit (has better performance) over HTML renderer - could display image with platform view:
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,
);
}
}

just add cors.json in web folder
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]

After creating cors.json and running the commands, nothing worked!
Finally what worked was adding a script into index.html inside your web folder.
<script type="text/javascript">window.flutterWebRenderer = "html";</script>
Reference Image:

it seems it solved my issue by running flutter run --web-renderer html

This official solution worked for me on Chrome only (Source). But I had to run it first every time.
flutter run -d chrome --web-renderer html
And disabling web security also worked (Source). But the browsers will show a warning banner.
But In case you are running on a different browser than Chrome (e.g. Edge) and you want to keep 'web security' enabled.
You can change the default web renderer in settings in VS Code
File ==> Preferences ==> Settings ==> Enter 'Flutter Web' in the Search Bar ==> Set the default web renderer to html

For someone who uses Slim Framework, just create a .htaccess file on that folder for storing images and put this line of code
Header set Access-Control-Allow-Origin *

There is a two way to solve this issue :
1- Just run your flutter web with flutter run -d chrome --web-renderer html
But there is one problem when you renderer your canvas view to HTML view. So your all views like images, text, etc gone blurry(bad quality). If you sacrifice the quality so go on with the first solution.
If you don't sacrifice quality so you need to add some code to your backend site I have done with node js you can use with yours.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
So, I chose the second solution because I don't sacrifice quality. So I provide you with my backend screenshot for better understanding hope you found your solution.

I had an issue while loading content from other domains which I don't have control over to change the cors settings from the server-side. I have found a work around for this problem.
STEP 1: go to C:\src\flutter\packages\flutter_tools\lib\src\web or navigate from your flutter root directory to flutter\packages\flutter_tools\lib\src\web.
STEP 2: open chrome.dart in your text editor.
STEP 3: add '--disable-web-security' under the like '--disable-extensions' as save the file.
STEP 4: run flutter clean in your project folder and run the app.
Hope this works for you.
I haven't tested my application in production yet. Adding this flag might also cause some security issues.

The Ultimate Solution
Use this package instead of flutter's NetworkImage.
https://pub.dev/packages/image_network
Tested on Flutter web with Canvas renderer and it works like a charm!

Verified answer is correct, Upvoted you man. Here's how I did it

Related

How to transform Flutter web app into a PWA?

I am making a new Web application with Flutter web.
I want to add service workers to my app in order to make it a PWA.
What I need to use to achieve my goal ?
I have tried to do it with dart packages (service_worker or pwa), but they are deprecated for Dart 2.
Since a service worker is just javascript code you can write one in plain javascript (e.g. in a sw.js file), bundle it with your flutter web app and then register the service worker from the index.html file like this (source):
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
You currently need to switch to Flutter Channel Dev (at Feb 17th 2020, current Dev version 1.15.3)
For existing projects, use the terminal to hit the command:
flutter create .
For new projects, you would have a 2 files: manifest.json and index.html inside your web folder.
While checking index.html you would notice the following script:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/flutter_service_worker.js');
});
}
If the script is not there, added inside <body></body>
This script creates the PWA support for you and be able to "install" the app on a device (this also includes MacOS)
Follow this GUIDE to complete your PWA functionalities.

Cannot pass the lighthouse audit for CRA PWA

I am trying to build a PWA with CRA and ran into some issues. However, even though I have registered the user (serviceWorker.register() in index.js) and can store the files in cache storage and run it offline, I still cannot pass the audit and I get (I've built my web app already, so it's running in production mode):
1.start_url does not respond with a 200 when offline Unable to fetch start URL via service worker.
2.Current page does not respond with a 200 when offline
3.Does not register a service worker that controls page and start_url
Which in my opinion is caused by wrong start_url.
I have a manifest.json and index.html in public folder and serviceWorker.js, index.js inside the src folder (inside public). and I get service-worker.js and manifest.json in the build folder after I build the app.
I've tried changing the start_url to "." , "index.html", "/" and some other options, but it did not change anything, still the same error.
Edit
I am also getting this
Network tab in Chrome
Console in Chrome
Error in this line in serviceWorker.js:
fetch(swUrl)
Seems like service-worker.js, manifest.json are not precached. This is weird, because from my understanding it should be precached automiatically. What is the solution here ?

ionic 4 sub paths not loading when running ionic serve

I had an ionic 4 beta project of --type=angular that was loading at any path without issue.
Periodically, i have been updating my packages by running an npm update and am currently at:
"#ionic/angular": "^4.0.2"
as well as updated installs for the ionic cli, and am currently at:
CLI 4.10.3
I am not sure when this app loading issue started, but i suspect it was after running the last npm update or update install of the cli.
When running ionic serve my application loads correctly, and i am able to navigate to all sub paths without any issues.
However, when:
• refreshing the browser while viewing a sub path
• attempting to enter a url with a sub path
• live reloading while viewing a sub path
the app attempts to load all js files relative to the sub path and fails to run like so:
http://localhost:8100/page/sub/path
fails to load because the app attempts to load runtime.js here:
http://localhost:8100/page/sub/path/runtime.js
my base href is currently set to ./
When i inspect the html source, the script tags are formatted as follows:
<script type="text/javascript" src="runtime.js"></script>
If i attempt to load a page directly at the root, the application loads ok without issue like so:
http://localhost:8100 loads OK
http://localhost:8100/page loads OK
So again to recap, the app only fails to load the js assets at a sub path.
Any idea where to begin troubleshooting?
For anyone running into this same problem, i have the answer.
I am not sure when or why, but my base href was set incorrectly and this was the problem.
I changed my base href from ./ to / and this solved my problem.

Chrome devtools save changed file path

I use browsersync and run site on local machine on http://localhost:3000/ — when i change css file (example path: ./static/css/menu.css/from devtools - it saved to root project folder in ./localhost%253a3000/static/css/menu.css
how can i change this path?
Thanks!
You got override locals featured enabled. You need to disabled it, and enable workspaces feature instead. I'm not giving all details because this features are different from chrome version to another. You can use the links to get workspaces working.

Can I make TypeKits fonts work locally even if I'm not using a webserver (no localhost)?

I'm just playing around with an index.html file and an accompanying CSS file that I'm viewing in my web browser. How do I allow this to work with TypeKit? I know I can have it work if I have a webserver with localhost running, but in this case I don't.
If you have some working webserver, you can configure the typekit to use that domain, upload the index.html there, and then rip the typekit CSS to use it locally. The fonts are included as data URIs.
To do that, for example, in Chrome: Open the dev tools, go to the network tab, reload the hosted page and look for a CSS file from use.typekit.net (d?abcde2134...). Then copy the data from the preview tab into a local CSS file and you're good to go.