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
相关产品推荐
相关产品推荐

