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

Flutter中如何使用Directory访问assets下的子目录?

核心原因

dart:io 提供的 Directory 类仅能访问设备本地文件系统上的真实物理目录。你在项目中配置的 assets 资源在应用打包阶段会被编译进APK/IPA二进制安装包内部,不会以独立文件的形式解压到设备本地文件系统,因此直接传入assets/subdirectory/这类路径调用Directory必然报找不到目录的错误,调整前缀、斜杠的方案都不会生效,因为该路径从一开始就不在IO接口可访问的文件系统范围内。
你平时用rootBundle.loadString('assets/xxx/xxx')能正常读取文件,是因为Flutter的AssetBundle机制直接从安装包的二进制资源段读取内容,和本地文件系统的路径解析逻辑完全独立。

检索指定前缀资产文件的实现方案

不要尝试用IO接口直接访问assets目录,通过Flutter打包时自动生成的资产清单即可完成筛选:

  • 第一步:确认所有需要检索的文件都已在pubspec.yaml的assets字段下正确声明,支持直接声明子目录(即你当前用的assets/[子目录名]/格式),只要资源会被打进安装包即可。
  • 第二步:运行时读取AssetManifest.json(Flutter打包时自动生成的全量资产列表文件),从中筛选符合路径要求、文件名前缀匹配的资源。

代码实现

import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

/// 检索指定assets子目录下,文件名以指定关键词开头的资源路径列表
/// [subDir] 目标子目录名,对应assets下的一级子目录
/// [keywordPrefix] 文件名匹配前缀
Future<List<String>> filterAssetsByPrefix(String subDir, String keywordPrefix) async {
  // 读取全量资产清单
  final manifestContent = await rootBundle.loadString('AssetManifest.json');
  final Map<String, dynamic> assetManifest = json.decode(manifestContent);

  final dirPathPrefix = 'assets/$subDir/';
  // 筛选匹配项
  return assetManifest.keys.where((assetPath) {
    // 过滤非目标目录下的资源
    if (!assetPath.startsWith(dirPathPrefix)) return false;
    // 提取纯文件名(去除目录前缀)
    final fileName = assetPath.replaceFirst(dirPathPrefix, '');
    // 匹配文件名前缀
    return fileName.startsWith(keywordPrefix);
  }).toList();
}

/// 如果业务需要用到IO可访问的真实文件路径,可以把资产写入临时目录后返回路径
Future<String> getAssetLocalPath(String assetPath) async {
  final byteData = await rootBundle.load(assetPath);
  final tempDir = await getTemporaryDirectory();
  final fileName = assetPath.split('/').last;
  final targetFile = File('${tempDir.path}/$fileName');
  await targetFile.writeAsBytes(
    byteData.buffer.asUint8List(
      byteData.offsetInBytes,
      byteData.lengthInBytes,
    ),
  );
  return targetFile.path;
}

调用示例

// 比如查找assets/subdirectory目录下,文件名以test开头的资源
final matchedAssetPaths = await filterAssetsByPrefix('subdirectory', 'test');
// 拿到路径后可直接通过rootBundle读取内容,或调用getAssetLocalPath转成本地IO路径使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:24:29