(转载仅作记录)Flutter加载https图片无法显示,受限证书问题

本文介绍了一种在Flutter中解决Image.network加载HTTPS图片时出现证书错误的方法。通过创建一个自定义的NetworkImageSSL类,该类覆盖了默认的网络请求,忽略证书验证,从而能够成功显示图片。只需将原来的Image.network替换为新的NetworkImageSSL即可。

找到的解决办法是这个:这里是原文链接点击这里

因为没有证书,直接用Image.network方法显示HTTPS图片时报错证书问题
新建一个工具类:NetworkImageSSL

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui show instantiateImageCodec, Codec;

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';

/// Image.network方法显示HTTPS图片时忽略证书
class NetworkImageSSL extends ImageProvider<NetworkImageSSL> {
  const NetworkImageSSL(this.url, {this.scale = 1.0, this.headers})
      : assert(url != null),
        assert(scale != null);

  final String url;

  final double scale;

  final Map<String, String> headers;

  @override
  Future<NetworkImageSSL> obtainKey(ImageConfiguration configuration) {
    return new SynchronousFuture<NetworkImageSSL>(this);
  }

  @override
  ImageStreamCompleter load(NetworkImageSSL key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(codec: _loadAsync(key), scale: key.scale);
  }

  static final HttpClient _httpClient = new HttpClient()
    ..badCertificateCallback =
    ((X509Certificate cert, String host, int port) => true);

  Future<ui.Codec> _loadAsync(NetworkImageSSL key) async {
    assert(key == this);

    final Uri resolved = Uri.base.resolve(key.url);
    final HttpClientRequest request = await _httpClient.getUrl(resolved);
    headers?.forEach((String name, String value) {
      request.headers.add(name, value);
    });
    final HttpClientResponse response = await request.close();
    if (response.statusCode != HttpStatus.ok)
      throw new Exception(
          'HTTP请求失败,状态码: ${response?.statusCode}, $resolved');

    final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
    if (bytes.lengthInBytes == 0)
      throw new Exception('NetworkImageSSL是一个空文件: $resolved');

    return await ui.instantiateImageCodec(bytes);
  }

  @override
  bool operator ==(dynamic other) {
    if (other.runtimeType != runtimeType) return false;
    final NetworkImageSSL typedOther = other;
    return url == typedOther.url && scale == typedOther.scale;
  }

  @override
  int get hashCode => hashValues(url, scale);

  @override
  String toString() => '$runtimeType("$url", scale: $scale)';
}

我原来的方法是

child: Image.network(imgurl, fit: BoxFit.fill,),

现在改为

new Image(image: NetworkImageSSL(imgurl), fit: BoxFit.cover)

这样就可以忽略证书,显示图片了

Flutter加载本地图片失败或显示异常,通常是由以下几个原因导致的:资源路径配置错误、资源未正确加载、或图片资源本身存在问题。以下是一些详细的解决方法和注意事项。 ### 1. 检查 `pubspec.yaml` 中的资源配置 确保图片资源的路径在 `pubspec.yaml` 文件中正确声明。路径必须以 `-` 开头,并且指向图片所在的目录。例如: ```yaml flutter: assets: - assets/images/ ``` 如果图片存放在 `assets/images/` 目录下,则可以直接使用相对路径引用,如 `assets/images/icon.png`。 如果路径配置错误,Flutter无法找到图片资源,导致加载失败 [^3]。 --- ### 2. 使用正确的 `ImageProvider` 在 Flutter加载本地图片时,推荐使用 `AssetImage` 为 `ImageProvider`。例如: ```dart Image( image: AssetImage("assets/images/icon.png"), width: 100, height: 100, ) ``` 确保路径与 `pubspec.yaml` 中配置的路径一致。如果路径错误,Flutter 会抛出 `Image provider: AssetImage(...)` 错误,并无法加载图片 [^3]。 --- ### 3. 检查图片文件名和扩展名 图片文件名和扩展名必须与代码中引用的完全一致。例如,如果图片文件名为 `icon.PNG`,但在代码中引用为 `icon.png`,则在某些系统上可能会加载失败。 --- ### 4. 确保资源文件位于正确的位置 图片资源应放置在项目根目录下的 `assets/images/`(或其他自定义路径)目录中。例如: ``` project_root/ ├── assets/ │ └── images/ │ └── icon.png ├── lib/ │ └── main.dart └── pubspec.yaml ``` 如果图片文件未放置在正确的目录中,Flutter无法将其打包到应用程序中,从而导致加载失败。 --- ### 5. 使用 `Image.asset` 简化加载 可以使用 `Image.asset` 构造函数直接加载本地图片资源,例如: ```dart Image.asset( "assets/images/icon.png", width: 100, height: 100, ) ``` 这种方式与 `AssetImage` 类似,但语法更简洁,适合快速加载资源。 --- ### 6. 添加图片加载失败的容错机制 为了增强用户体验,可以在图片加载失败时显示默认图片。例如,封装一个 `ImageWidget` 来处理加载失败的情况: ```dart class ImageWidget extends StatefulWidget { final String url; final double? w; final double? h; final String defImagePath; ImageWidget({required this.url, this.w, this.h, this.defImagePath = "assets/images/default.png"}); @override _ImageWidgetState createState() => _ImageWidgetState(); } class _ImageWidgetState extends State<ImageWidget> { bool _hasError = false; @override Widget build(BuildContext context) { return Image.asset( _hasError ? widget.defImagePath : widget.url, width: widget.w, height: widget.h, errorBuilder: (context, error, stackTrace) { _hasError = true; return Image.asset(widget.defImagePath, width: widget.w, height: widget.h); }, ); } } ``` 通过 `errorBuilder` 属性,可以在加载失败时切换到默认图片,提升用户体验 [^2]。 --- ### 7. 清理并重新构建项目 有时,旧的构建缓存可能导致资源加载异常。可以尝试运行以下命令清理并重新构建项目: ```bash flutter clean flutter pub get flutter run ``` --- ### 8. 检查 Flutter 版本 不同版本的 Flutter 对资源加载的支持可能有所不同。如果使用的是较旧版本,建议升级到最新版本,以确保资源加载功能的稳定性。 --- ### 9. 使用调试工具检查资源加载 可以使用 Flutter 的调试工具(如 `flutter doctor` 和 `flutter analyze`)检查项目配置是否存在问题。此外,还可以在运行时打印资源路径,确认路径是否正确。 --- ### 示例代码:加载本地图片并处理失败情况 ```dart Image.asset( "assets/images/icon.png", width: 100, height: 100, errorBuilder: (context, error, stackTrace) { return Image.asset("assets/images/default.png", width: 100, height: 100); }, ) ``` 通过 `errorBuilder` 属性,可以在加载失败时显示默认图片,避免界面空白 [^2]。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值