【Flutter 實戰】檔案系統目錄
阿新 • • 發佈:2020-09-18
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064927647-600712682.png)
> **老孟導讀**:Flutter 中獲取檔案路徑,我們都知道使用 **path_provider**,但對其目錄對含義不是很清楚,此文介紹 Android、iOS 系統的檔案目錄,不同場景下建議使用的目錄。
不同的平臺對應的檔案系統是不同的,比如檔案路徑,因此 Flutter 中獲取檔案路徑需要原生支援,原生端通過 MethodChannel 傳遞檔案路徑到 Flutter,如果沒有特殊的需求,推薦大家使用 Google 官方維護的外掛 **path_provider**。
> pub 地址:[https://pub.flutter-io.cn/packages/path_provider](https://pub.flutter-io.cn/packages/path_provider)
>
> Github 地址:[https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider](https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider)
### 新增依賴
在專案的 `pubspec.yaml` 檔案中新增依賴:
```dart
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**
臨時目錄,適用於下載的快取檔案,此目錄隨時可以清除,此目錄為應用程式私有目錄,其他應用程式無法訪問此目錄。
Android 上對應`getCacheDir`。
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 檔案儲存
Android 檔案儲存分為**內部儲存**和**外部儲存**。
#### 內部儲存
用於儲存應用的私有檔案,其他應用無法訪問這些資料,建立的檔案在此應用的包名目錄下,沒有 **root 許可權** 的手機無法在手機的 **檔案管理** 應用中看到此目錄,不過可以通過 Android Studio 工具檢視,路徑為:data/data/包名:
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064928178-978188697.png)
看下包名下具體的目錄結構:
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064928347-1999515585.png)
- cache 目錄:對應 **getTemporaryDirectory** 方法,用於快取檔案,此目錄隨時可能被系統清除。
- files 目錄:對應 **getApplicationSupportDirectory** 方法。
- code_cache:此目錄儲存 Flutter 相關程式碼和資源。
- flutter_engine/skia:Flutter 渲染引擎。
- flutter_guidePVWGWK/flutter_guide/build/flutter_assets:Flutter 資原始檔。
- shared_prefs: **SharePreferences** 的預設路徑。
- app_flutter:對應 **getApplicationDocumentsDirectory**方法。
- app_flutter/dbName:使用 **sqlite** 的預設路徑,**sqlite** 也可以指定位置。
**SharePreferences** 和 **sqlite** 是兩種儲存資料的第三方外掛。
內部儲存的特點:
- 安全性,其他應用無法訪問這些資料。
- 當應用解除安裝的時候,這些資料也會被刪除,避免垃圾檔案。
- 不需要申請額外許可權。
- 儲存的空間有限,此目錄資料隨時可能被系統清除,也可以通過 **設定** 中的 **清除資料** 可以清除此目錄資料。
- **國內特色**,不同手機廠商對此目錄做了不同的限制,比如總體大小限制、單個應用程式所佔空間大小限制、清除資料策略不同等。
#### 外部儲存
外部儲存可以通過手機的 **檔案管理** 應用檢視,
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064928554-2103294065.jpg)
這裡面有一個特殊的目錄:Android/data/包名:
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064928728-880725581.png)
看到這個目錄是不是覺得和內部儲存目錄非常相似,一個包名代表一個應用程式:
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064928957-236386613.png)
- cache:快取目錄,對應 **getExternalCacheDirectories** 方法。
- files:對應 **getExternalStorageDirectories** 方法。
此目錄的特點:
- 當應用解除安裝的時候,這些資料也會被刪除,避免垃圾檔案。
- 不需要申請額外許可權。
- 空間大且不會被系統清除,通過 **設定** 中的 **清除資料** 可以清除此目錄資料。
- 使用者可以直接對檔案進行刪除、匯入操作。
外部儲存除了 **Android/data/** 目錄,還有和此目錄同級的目錄,特點:
- 所有應用程式均可訪問。
- 使用者可以直接對檔案進行刪除、匯入操作。
- 需要申請**讀寫許可權**。
Android 官方對此目錄的管理越來越嚴格, **Android 11** 系統已經開始強制執行分割槽儲存,詳情見:[https://developer.android.com/preview/privacy/storage?hl=zh-cn](https://developer.android.com/preview/privacy/storage?hl=zh-cn)
上面說了這麼多,總結如下:
- **SharePreferences** 和 **sqlite** 資料建議存放在內部儲存,外掛已經幫我們完成了,無需手動處理。
- 嚴格保密的資料,比如使用者資料,建議存放在內部儲存,對應 **getApplicationSupportDirectory** 方法。
- 其餘所有的資料建議存放 **Android/data/包名/** ,對應 **getExternalCacheDirectories** 和 **getExternalStorageDirectories** 方法。
### iOS 檔案儲存
iOS 檔案儲存相比 Android 要簡單的多,因為 iOS 對使用者隱私保護非常嚴格,每個 iOS 應用程式都有一個單獨的檔案系統,而且只能在對應的檔案系統中進行操作,此區域被稱為沙盒。
每個應用沙盒含有3個資料夾:Documents, Library 和 tmp:
![](https://img2020.cnblogs.com/other/467322/202009/467322-20200918064929323-482694394.png)
- Documents:應用程式資料檔案寫入到這個目錄下。這個目錄用於儲存使用者資料。儲存應用程式的重要資料檔案和使用者資料檔案等。iTunes 同步時會備份該目錄,對應 **getApplicationDocumentsDirectory** 方法。
- Library:對應 **getLibraryDirectory** 方法。
- Caches:儲存應用程式使用時產生的支援檔案、快取檔案、日誌檔案等,比如下載的音樂,視訊,SDWebImage快取等。對應 **getTemporaryDirectory** 方法。
- Preferences:包含應用程式的偏好設定檔案,iCloud會備份設定資訊。
- Application Support:對應 **getApplicationSupportDirectory** 方法。
- tmp:存放臨時檔案,不會被備份,而且這個檔案下的資料有可能隨時被清除的可能,按照官方說法每三天清理一次快取資料。
### path_provider 使用
```dart
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 exten