You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何缓存HTML格式API响应的网络图片以实现离线显示?

Flutter离线渲染HTML图片解决方案

方案一:用CachedNetworkImage配合flutter_html自定义渲染

借助cached_network_image的自动缓存能力,接管flutter_html中img标签的渲染逻辑,实现离线加载。

步骤1:添加依赖

在pubspec.yaml中引入所需包:

dependencies:
  flutter_html: ^3.0.0
  cached_network_image: ^3.2.3
  shared_preferences: ^2.2.2

步骤2:修改渲染代码

通过customRender自定义图片渲染,替换默认的img标签处理:

Html(
  data: data.description,
  customRender: {
    "img": (context, attributes, _) {
      final imgUrl = attributes["src"];
      if (imgUrl == null) return const SizedBox.shrink();
      
      // 解析原HTML中的宽高样式
      final widthStr = attributes["style"]?.split("width:")[1]?.split("px")[0];
      final heightStr = attributes["style"]?.split("height:")[1]?.split("px")[0];

      return CachedNetworkImage(
        imageUrl: imgUrl,
        placeholder: (context, url) => const CircularProgressIndicator(strokeWidth: 2),
        errorWidget: (context, url, error) => const Icon(Icons.broken_image, color: Colors.grey),
        cacheManager: DefaultCacheManager(),
        fit: BoxFit.contain,
        width: widthStr != null ? double.parse(widthStr) : null,
        height: heightStr != null ? double.parse(heightStr) : null,
      );
    }
  },
)

该方案会自动缓存图片到本地,无网络时直接读取缓存文件,无需额外处理HTML内容。

方案二:预下载图片并替换HTML路径(完全离线场景)

如果需要确保完全无网络时也能显示图片,可在首次获取数据时下载图片到本地存储,替换HTML中的图片URL为本地路径后再缓存。

步骤1:添加依赖

额外引入文件操作和网络下载相关包:

dependencies:
  flutter_html: ^3.0.0
  shared_preferences: ^2.2.2
  path_provider: ^2.0.15
  dio: ^5.3.2

步骤2:实现图片下载与HTML替换

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

// 处理HTML,下载图片并替换为本地路径
Future<String> cacheHtmlImages(String originalHtml) async {
  final imgRegex = RegExp(r'<img[^>]+src="([^"]+)"');
  final matches = imgRegex.allMatches(originalHtml);
  String processedHtml = originalHtml;

  final dio = Dio();
  final appDir = await getApplicationDocumentsDirectory();

  for (var match in matches) {
    final imgUrl = match.group(1);
    if (imgUrl == null) continue;

    // 生成本地存储路径
    final fileName = imgUrl.split('/').last;
    final localFilePath = '${appDir.path}/$fileName';
    final localFile = File(localFilePath);

    // 仅当文件不存在时下载
    if (!await localFile.exists()) {
      await dio.download(imgUrl, localFilePath);
    }

    // 替换在线URL为本地文件路径
    processedHtml = processedHtml.replaceAll(imgUrl, 'file://$localFilePath');
  }

  // 保存处理后的HTML到SharedPreferences
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('cached_desc', processedHtml);

  return processedHtml;
}

步骤3:渲染处理后的HTML

Html(
  data: cachedHtmlContent, // 从SharedPreferences读取的处理后HTML
  onImageError: (_, __) => const Icon(Icons.broken_image, color: Colors.grey),
)

注意事项

  • 方案一无需修改原始HTML,依赖cached_network_image的缓存策略,适合大多数场景
  • 方案二需要管理本地文件,可定期清理过期图片避免占用过多存储空间
  • Android/iOS需确保应用拥有文件访问权限(应用内部目录无需额外申请)

内容的提问来源于stack exchange,提问作者Ashish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 18:06:17