[Flutter] CachedNetworkImage加载图片证书校验失败

CachedNetworkImage 在加载某些https网站的图像时会出现类似这样的错误:

I/flutter: The following HandshakeException was thrown resolving an image codec:
    Handshake error in client (OS Error: 
        CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:352))
08-05 16:27:56.673 13676-13696/com.example.flutter_module.host I/flutter: When the exception was thrown, this was the stack:
08-05 16:27:56.688 13676-13696/com.example.flutter_module.host I/flutter: #0      NetworkImage._loadAsync (package:flutter/src/painting/image_provider.dart:490:39)

 

这就是证书问题了。

CachedNetworkImage 提供了一个参数 cacheManager , 一般我们都不会指定,那么它会使用 DefaultCacheManager 。DefaultCacheManager 中会使用一个 FileService 来下载图像。那么,我们只需要做一个 CacheManager ,并自定义一个 FileService 就可以解决此问题了。具体代码如下:

import 'dart:async';

import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:http/http.dart' as http;
import 'dart:io';

/// 缓存管理
class EsoImageCacheManager extends CacheManager {
  static const key = 'libEsoCachedImageData';

  static EsoImageCacheManager _instance;
  factory EsoImageCacheManager() {
    _instance ??= EsoImageCacheManager._();
    return _instance;
  }

  EsoImageCacheManager._() : super(Config(key, fileService: EsoHttpFileService()));
}

class EsoHttpFileService extends FileService {
  HttpClient _httpClient;
  EsoHttpFileService({HttpClient httpClient}) {
    _httpClient = httpClient ?? HttpClient();
    _httpClient.badCertificateCallback = (cert, host, port) => true;
  }

  @override
  Future<FileServiceResponse> get(String url,
      {Map<String, String> headers = const {}}) async {
    final Uri resolved = Uri.base.resolve(url);
    final HttpClientRequest req = await _httpClient.getUrl(resolved);
    headers?.forEach((key, value) {
      req.headers.add(key, value);
    });
    final HttpClientResponse httpResponse = await req.close();
    final http.StreamedResponse _response = http.StreamedResponse(
      httpResponse.timeout(Duration(seconds: 60)), httpResponse.statusCode,
      contentLength: httpResponse.contentLength,
      reasonPhrase: httpResponse.reasonPhrase,
      isRedirect: httpResponse.isRedirect,
    );
    return HttpGetResponse(_response);
  }
}

 

使用方法:

CachedNetworkImage(
    imageUrl: url, 
    fit: BoxFit.cover,
    cacheManager: EsoImageCacheManager()
)

 

经测试,问题解决。

 

posted @ 2020-11-24 16:05  我爱我家喵喵  阅读(3131)  评论(0编辑  收藏  举报