老孟导读:Flutter 中获取文件路径,咱们都知道使用 path_provider,但对其目录对含义不是很清楚,此文介绍 Android、iOS 系统的文件目录,不一样场景下建议使用的目录。android
不一样的平台对应的文件系统是不一样的,好比文件路径,所以 Flutter 中获取文件路径须要原生支持,原生端经过 MethodChannel 传递文件路径到 Flutter,若是没有特殊的需求,推荐你们使用 Google 官方维护的插件 path_provider。ios
pub 地址:https://pub.flutter-io.cn/packages/path_providergit
Github 地址:https://github.com/flutter/plugins/tree/master/packages/path_provider/path_providergithub
在项目的 pubspec.yaml
文件中添加依赖:sql
dependencies: path_provider: ^1.6.14
执行命令:缓存
flutter pub get
path_provider(版本:1.6.14)提供了8个方法获取不一样的文件路径,目前 Flutter(Flutter 1.20.1 • channel stable )只发布了正式版本的 Android 和 iOS,所以下面仅介绍 Android 和 iOS 平台的文件路径。安全
getTemporaryDirectory微信
临时目录,适用于下载的缓存文件,此目录随时能够清除,此目录为应用程序私有目录,其余应用程序没法访问此目录。app
Android 上对应getCacheDir
。ide
iOS上对应NSCachesDirectory
。
getApplicationSupportDirectory
应用程序能够在其中放置应用程序支持文件的目录的路径。
将此文件用于您不想向用户公开的文件。 您的应用不该将此目录用于存放用户数据文件。
在iOS上,对应NSApplicationSupportDirectory
,若是此目录不存在,则会自动建立。
在Android上,对应getFilesDir
。
getLibraryDirectory
应用程序能够在其中存储持久性文件,备份文件以及对用户不可见的文件的目录路径,例如storage.sqlite.db。
在Android上,此函数抛出[UnsupportedError]异常,没有等效项路径存在。
getApplicationDocumentsDirectory
应用程序可能在其中放置用户生成的数据或应用程序没法从新建立的数据的目录路径。
在iOS上,对应NSDocumentDirectory
API。 若是数据不是用户生成的,考虑使用[getApplicationSupportDirectory]。
在Android上,对应getDataDirectory
API。 若是要让用户看到数据,请考虑改用[getExternalStorageDirectory]。
getExternalStorageDirectory
应用程序能够访问顶级存储的目录的路径。因为此功能仅在Android上可用,所以应在发出此函数调用以前肯定当前操做系统。
在iOS上,此功能会引起[UnsupportedError]异常,由于没法在应用程序的沙箱外部访问。
在Android上,对应getExternalFilesDir(null)
。
getExternalCacheDirectories
存储特定于应用程序的外部缓存数据的目录的路径。 这些路径一般位于外部存储(如单独的分区或SD卡)上。 电话可能具备多个可用的存储目录。
因为此功能仅在Android上可用,所以应在发出此函数调用以前肯定当前操做系统。
在iOS上,此功能会抛出UnsupportedError,由于这是不可能的在应用程序的沙箱外部访问。
在Android上,对应Context.getExternalCacheDirs()
或API Level 低于19的Context.getExternalCacheDir()
。
getExternalStorageDirectories
能够存储应用程序特定数据的目录的路径。 这些路径一般位于外部存储(如单独的分区或SD卡)上。
因为此功能仅在Android上可用,所以应在发出此函数调用以前肯定当前操做系统。
在iOS上,此功能会抛出UnsupportedError,由于这是不可能的在应用程序的沙箱外部访问。
在Android上,对应Context.getExternalFilesDirs(String type)
或API Level 低于19的Context.getExternalFilesDir(String type)
。
getDownloadsDirectory
存储下载文件的目录的路径,这一般仅与台式机操做系统有关。
在Android和iOS上,此函数将引起[UnsupportedError]异常。
若是没有 Android 或者 iOS开发经验,看完上面的说明应该是一脸懵逼的,这么多路径到底用哪一个?有什么区别?下面从 Android 和 iOS 平台的角度介绍其文件路径,最后给出路径使用的建议以及使用过程当中须要注意的事项。
Android 文件存储分为内部存储和外部存储。
用于保存应用的私有文件,其余应用没法访问这些数据,建立的文件在此应用的包名目录下,没有 root 权限 的手机没法在手机的 文件管理 应用中看到此目录,不过能够经过 Android Studio 工具查看,路径为:data/data/包名:
看下包名下具体的目录结构:
SharePreferences 和 sqlite 是两种保存数据的第三方插件。
内部存储的特色:
外部存储能够经过手机的 文件管理 应用查看,
这里面有一个特殊的目录:Android/data/包名:
看到这个目录是否是以为和内部存储目录很是类似,一个包名表明一个应用程序:
此目录的特色:
外部存储除了 Android/data/ 目录,还有和此目录同级的目录,特色:
Android 官方对此目录的管理愈来愈严格, Android 11 系统已经开始强制执行分区存储,详情见:https://developer.android.com/preview/privacy/storage?hl=zh-cn
上面说了这么多,总结以下:
iOS 文件存储相比 Android 要简单的多,由于 iOS 对用户隐私保护很是严格,每一个 iOS 应用程序都有一个单独的文件系统,并且只能在对应的文件系统中进行操做,此区域被称为沙盒。
每一个应用沙盒含有3个文件夹:Documents, Library 和 tmp:
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; /// /// desc: /// class PathProviderDemo extends StatefulWidget { @override _PathProviderDemoState createState() => _PathProviderDemoState(); } class _PathProviderDemoState extends State<PathProviderDemo> { Future<Directory> _tempDirectory; Future<Directory> _appSupportDirectory; Future<Directory> _appLibraryDirectory; Future<Directory> _appDocumentsDirectory; Future<Directory> _externalStorageDirectory; Future<List<Directory>> _externalStorageDirectories; Future<List<Directory>> _externalCacheDirectories; Future<Directory> _downloadDirectory; @override void initState() { super.initState(); setState(() { _tempDirectory = getTemporaryDirectory(); _appSupportDirectory = getApplicationSupportDirectory(); _appLibraryDirectory = getLibraryDirectory(); _appDocumentsDirectory = getApplicationDocumentsDirectory(); _externalStorageDirectory = getExternalStorageDirectory(); _externalCacheDirectories = getExternalCacheDirectories(); _externalStorageDirectories = getExternalStorageDirectories(); _downloadDirectory = getDownloadsDirectory(); }); } Widget _buildDirectory( BuildContext context, AsyncSnapshot<Directory> snapshot) { Text text = const Text(''); if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { text = Text('Error: ${snapshot.error}'); } else if (snapshot.hasData) { text = Text('path: ${snapshot.data.path}'); } else { text = const Text('path unavailable'); } } return Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: text); } Widget _buildDirectories( BuildContext context, AsyncSnapshot<List<Directory>> snapshot) { Text text = const Text(''); if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { text = Text('Error: ${snapshot.error}'); } else if (snapshot.hasData) { final String combined = snapshot.data.map((Directory d) => d.path).join(', '); text = Text('paths: $combined'); } else { text = const Text('path unavailable'); } } return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: text); } Widget _buildItem(String title, Future<Directory> future) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text(title), ), FutureBuilder<Directory>(future: future, builder: _buildDirectory), ], ); } Widget _buildItem1(String title, Future<List<Directory>> future) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text(title), ), FutureBuilder<List<Directory>>( future: future, builder: _buildDirectories), ], ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: ListView( itemExtent: 120, children: <Widget>[ _buildItem('getTemporaryDirectory', _tempDirectory), _buildItem('getApplicationSupportDirectory', _appSupportDirectory), _buildItem('getLibraryDirectory', _appLibraryDirectory), _buildItem( 'getApplicationDocumentsDirectory', _appDocumentsDirectory), _buildItem( 'getExternalStorageDirectory', _externalStorageDirectory), _buildItem('getDownloadsDirectory', _downloadDirectory), _buildItem1('getExternalStorageDirectories',_externalStorageDirectories), _buildItem1('getExternalCacheDirectories',_externalCacheDirectories), ], ), ), ); } }
Android 系统各个路径:
iOS 系统各个路径:
老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:
![]() |
![]() |