Flutter 程序在 Chrome 上运行正常,但在 Web 服务器上无法正常运行

Posted

技术标签:

【中文标题】Flutter 程序在 Chrome 上运行正常,但在 Web 服务器上无法正常运行【英文标题】:flutter program work okay on chrome, but cannot work correctly on web server 【发布时间】:2020-09-16 13:36:16 【问题描述】:

我是 Flutter 的新手,编写了以下 Flutter 程序来获取客户端 IP 地址和位置。我正在呼叫“http://ip-api.com/json”以获取 IP 地址和位置信息。该程序通过使用设备“chrome”和“web server”可以正常工作,我可以在页面上打印客户端的位置。 . 当我部署到 github 网页或 firebase 托管时,程序永远显示“加载循环”。程序部署到github web服务器(或其他web服务器)后,似乎无法获取ip地址。

一旦我将程序部署到 Github html 页面或 firebase 托管,我发现该程序抛出“XMLHTTPRequest 错误”。它在本地 Web 服务器或 chrome 上运行良好。对此有何建议?非常感谢。

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class IP_info
  final String IP;
  final String city;
  final String ZIP;
  final String st_code;
  final String state_name;
  final String country_code;
  final String country_name;

  IP_info(this.IP, this.city, this.st_code,this.ZIP, 
     this.state_name,this.country_code,this.country_name);

  factory IP_info.fromJson(Map<String, dynamic> json)
    return IP_info(
      IP:json['query'],
      ZIP:json['zip'],
      city:json['city'],
      country_code:json['countryCode'],
      st_code:json['region'],
      country_name:json['country_name'],
      state_name:json['regionName'],
    );
  


void main() 
  runApp(MaterialApp(
      title: 'Covid 19 cases near you',
      home: MyApp()
  ),
  );




class MyApp extends StatefulWidget
  @override
  State<StatefulWidget> createState()  => MyAppState();


class MyAppState extends State<MyApp> 

  bool _isLoading = false;
  IP_info ip_info;

  @override
  void initState() 
     _isLoading=true;
    _getPublicIP();
  

_getPublicIP() async 
    try 

      const url = 'http://ip-api.com/json';

      final response = await http.get(url);
      if (response.statusCode == 200) 
        ip_info = IP_info.fromJson(json.decode(response.body));
        print(ip_info.toString());

        setState(() 
          _isLoading = false;
        );
        
      else 
        // The request failed with a non-200 code
        print(response.statusCode);
        print(response.body);
      



     catch (e) 
      print(e);
    
  

 @override
  Widget build(BuildContext context) 
    return  Scaffold(
        appBar: AppBar(title: Text('Testing IP address'),    ),
        body: Container(
          padding: const EdgeInsets.all(8.0),
          decoration: BoxDecoration(
            color: Colors.white,
          ),
          child: _isLoading? Center(
              child: Column(children: [
                CircularProgressIndicator(),
                SizedBox(height: 10,),
                Text("Loading your location infomation ...", style: TextStyle(color: Colors.blueAccent),),
              ]
              )
          )
              : new Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center ,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget> [
              Text('You are in $ip_info.city $ip_info.state_name ',
                style: TextStyle(
                  fontWeight: FontWeight.bold,),
              ),

            ],
          ),
        )
    );
  

【问题讨论】:

【参考方案1】:

这可能是因为只为发布构建生成的服务工作者文件。服务工作文件的 credentials: 'include' 部分会中断所有没有Access-Control-Allow-Origin 或值为* 的请求,这些请求都是公共API。

上面有一个issue,据说master里已经修复了,还没有发布。因此,您目前可以做的一些解决方法是在每次构建后手动删除credentials 部分或取消注册服务工作者。

如果您仍想使用 Service Worker,可以通过以下方法移除该部分。 build/web 文件夹内应该有一个 flutter_service_worker.js 文件。您会发现凭证部分是 fetch 函数的第二个参数。您可以删除该参数。但这样做的坏处是每次构建后您都必须手动删除该部分,这既不是程序化的也不是有效的。

解决此问题的最佳方法是完全取消注册 Service Worker。您可以通过从 web/index.html 文件中删除此脚本部分来做到这一点。

<script>
      if ("serviceWorker" in navigator) 
        window.addEventListener("load", function() 
          navigator.serviceWorker.register("/flutter_service_worker.js");
        );
      
</script>

【讨论】:

非常感谢 Frenco 看一看这个。我在代码中添加了“CircularProgressIndicator()”函数(请参见上文)。但是在我部署到 Web 服务器后,代码仍然无法正常工作。我正在使用主通道进行颤动。您能建议我可以删除哪个程序“凭据:'包含'”吗?感谢您的指示。 嗨,Frenco,我在 web/index.html 文件中注释掉了 service worker 部分,但是一旦我将代码部署到 github html 或 firebase 托管,我仍然得到一个空白页面。 我认为你是对的。可能与一些设置问题有关。 @JoeZhou web/index.html 文件更新后你又重建了对吧?因为如果没有,你必须这样做。 感谢弗朗科!一旦我用“flutter build web”重建,web/index.html 就会用“Service Worker”部分重新生成。我这里是菜鸟。 “flutter build web”是正确的构建命令吗?【参考方案2】:

我切换到geolocation-db.com/json(而不是使用'ip-api.com/json)来获取客户端节点的位置信息,它可以工作!我认为这与服务器端有关。我认为这可能与网络请求必须是 https 而不是 http 有关。

【讨论】:

以上是关于Flutter 程序在 Chrome 上运行正常,但在 Web 服务器上无法正常运行的主要内容,如果未能解决你的问题,请参考以下文章

如何从 IDE 在移动 chrome 上运行 Flutter Web

Flutter Application release apk 在真实设备上无法正常工作

Flutter Web - 如何在桌面上的 Chrome 中测试 Flutter Web 应用程序打开?

在 Web 上运行的 Flutter 应用程序失败并出现错误:只有 JS 互操作成员可能是“外部的”

如何使用检查器在 Safari 上调试 Flutter Web App?

Flutter:在浏览器中运行网页版时如何停止显示移动应用