This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 55).
Expo 文件系统(旧版)
一个提供访问设备本地文件系统的库。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
重要
FileSystemAPI 的legacy版本包含在expo-file-system库中。出于向后兼容的原因,它可以与现代 API 一起使用。
expo-file-system 提供对存储在设备本地的文件系统的访问。它还能够从网络 URL 上传和下载文件。
安装
- npx expo install expo-file-systemIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
下载文件
const callback = downloadProgress => { const progress = downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite; this.setState({ downloadProgress: progress, }); }; const downloadResumable = FileSystem.createDownloadResumable( 'https://example.com/videos/small.mp4', FileSystem.documentDirectory + 'small.mp4', {}, callback ); try { const { uri } = await downloadResumable.downloadAsync(); console.log('已完成下载到 ', uri); } catch (e) { console.error(e); } try { await downloadResumable.pauseAsync(); console.log('已暂停下载操作,保存以供将来恢复'); AsyncStorage.setItem('pausedDownload', JSON.stringify(downloadResumable.savable())); } catch (e) { console.error(e); } try { const { uri } = await downloadResumable.resumeAsync(); console.log('已完成下载到 ', uri); } catch (e) { console.error(e); } //要在应用重启后恢复下载,假设 DownloadResumable.savable() 对象已被存储: const downloadSnapshotJson = await AsyncStorage.getItem('pausedDownload'); const downloadSnapshot = JSON.parse(downloadSnapshotJson); const downloadResumable = new FileSystem.DownloadResumable( downloadSnapshot.url, downloadSnapshot.fileUri, downloadSnapshot.options, callback, downloadSnapshot.resumeData ); try { const { uri } = await downloadResumable.resumeAsync(); console.log('已完成下载到 ', uri); } catch (e) { console.error(e); }
管理 Giphy
import * as FileSystem from 'expo-file-system/legacy'; const gifDir = FileSystem.cacheDirectory + 'giphy/'; const gifFileUri = (gifId: string) => gifDir + `gif_${gifId}_200.gif`; const gifUrl = (gifId: string) => `https://media1.giphy.com/media/${gifId}/200.gif`; // 检查 gif 目录是否存在。如果不存在,则创建它 async function ensureDirExists() { const dirInfo = await FileSystem.getInfoAsync(gifDir); if (!dirInfo.exists) { console.log("Gif 目录不存在,正在创建…"); await FileSystem.makeDirectoryAsync(gifDir, { intermediates: true }); } } // 下载所有指定为 ID 数组的 gifs export async function addMultipleGifs(gifIds: string[]) { try { await ensureDirExists(); console.log('正在下载', gifIds.length, '个 gif 文件…'); await Promise.all(gifIds.map(id => FileSystem.downloadAsync(gifUrl(id), gifFileUri(id)))); } catch (e) { console.error("无法下载 gif 文件:", e); } } // 返回本地 gif 文件的 URI // 如果本地不存在该 gif,则会下载它 export async function getSingleGif(gifId: string) { await ensureDirExists(); const fileUri = gifFileUri(gifId); const fileInfo = await FileSystem.getInfoAsync(fileUri); if (!fileInfo.exists) { console.log("Gif 未缓存在本地。正在下载…"); await FileSystem.downloadAsync(gifUrl(gifId), fileUri); } return fileUri; } // 导出可共享的 URI - 它可以在应用外部共享 export async function getGifContentUri(gifId: string) { return FileSystem.getContentUriAsync(await getSingleGif(gifId)); } // 删除整个 giphy 目录及其所有内容 export async function deleteAllGifs() { console.log('正在删除所有 GIF 文件…'); await FileSystem.deleteAsync(gifDir); }
服务端:处理 multipart 请求
Node.js 中的简单服务器,可以将上传的图片保存到磁盘:
const express = require('express'); const app = express(); const fs = require('fs'); const multer = require('multer'); const upload = multer({ dest: 'uploads/' }); // 此方法会将请求的二进制内容保存为文件。 app.patch('/binary-upload', (req, res) => { req.pipe(fs.createWriteStream('./uploads/image' + Date.now() + '.png')); res.end('OK'); }); // 此方法会将请求中的 "photo" 字段保存为文件。 app.patch('/multipart-upload', upload.single('photo'), (req, res) => { // 你可以访问其他 HTTP 参数。它们位于 body 对象中。 console.log(req.body); res.end('OK'); }); app.listen(3000, () => { console.log('运行在端口 3000'); });
API
import * as FileSystem from 'expo-file-system/legacy';
目录
该 API 使用指向设备上本地文件的 file:// URI 来标识文件。每个应用只有对以下目录下的位置具有读写权限:
例如,应用用户文档目录中 'myDirectory' 下名为 'myFile' 的文件,其 URI 将是 FileSystem.documentDirectory + 'myDirectory/myFile'。
用于创建文件的 Expo API 通常在这些目录中运行。这包括 Audio 录音、Camera 照片、ImagePicker 结果、SQLite 数据库以及 takeSnapShotAsync() 的结果。这使它们能够与 FileSystem API 一起使用。
某些 FileSystem 函数能够从其他位置读取(但不能写入)文件。
SAF URI
SAF URI 是与 Storage Access Framework 兼容的 URI。它应当类似于这样:content://com.android.externalstorage.*。
获取此类 URI 最简单的方法是通过 requestDirectoryPermissionsAsync 方法。
Constants
Type: string | null
URI to the directory where assets bundled with the application are stored.
Type: string | null
file:// URI pointing to the directory where temporary files used by this app will be stored.
Files stored here may be automatically deleted by the system when low on storage.
Example uses are for downloaded or generated files that the app just needs for one-time usage.
Type: string | null
file:// URI pointing to the directory where user documents for this app will be stored.
Files stored here will remain until explicitly deleted by the app. Ends with a trailing /.
Example uses are for files the user saves that they expect to see again.
Classes
Type: Class extends FileSystemCancellableNetworkTask<DownloadProgressData>
DownloadResumable Properties
DownloadResumable Methods
Promise<void>Download the contents at a remote URI to a file in the app's file system.
Promise<FileSystemDownloadResult | undefined>Returns a Promise that resolves to FileSystemDownloadResult object, or to undefined when task was cancelled.
Pause the current download operation. resumeData is added to the DownloadResumable object after a successful pause operation.
Returns an object that can be saved with AsyncStorage for future retrieval (the same object that is returned from calling FileSystem.DownloadResumable.savable()).
Promise<DownloadPauseState>Returns a Promise that resolves to DownloadPauseState object.
Resume a paused download operation.
Promise<FileSystemDownloadResult | undefined>Returns a Promise that resolves to FileSystemDownloadResult object, or to undefined when task was cancelled.
Method to get the object which can be saved with AsyncStorage for future retrieval.
DownloadPauseStateReturns object in shape of DownloadPauseState type.
FileSystemCancellableNetworkTask Methods
Promise<void>Type: Class extends FileSystemCancellableNetworkTask<UploadProgressData>
UploadTask Methods
Promise<void>Promise<FileSystemUploadResult | null | undefined>Methods
| Parameter | Type | Description |
|---|---|---|
| options | RelocatingOptions | A map of move options represented by |
Create a copy of a file or directory. Directories are recursively copied with all of their contents. It can be also used to copy content shared by other apps to local filesystem.
Promise<void>FileSystem Legacy.createDownloadResumable(uri, fileUri, options, callback, resumeData)
| Parameter | Type | Description |
|---|---|---|
| uri | string | The remote URI to download from. |
| fileUri | string | The local URI of the file to download to. If there is no file at this URI, a new one is created. If there is a file at this URI, its contents are replaced. The directory for the file must exist. |
| options(optional) | DownloadOptions | A map of download options represented by |
| callback(optional) | FileSystemNetworkTaskProgressCallback<DownloadProgressData> | This function is called on each data write to update the download progress.
|
| resumeData(optional) | string | The string which allows the api to resume a paused download. This is set on the |
Create a DownloadResumable object which can start, pause, and resume a download of contents at a remote URI to a file in the app's file system.
Note: You need to call
downloadAsync(), on aDownloadResumableinstance to initiate the download. TheDownloadResumableobject has a callback that provides download progress updates. Downloads can be resumed across app restarts by usingAsyncStorageto store theDownloadResumable.savable()object for later retrieval. Thesavableobject contains the arguments required to initialize a newDownloadResumableobject to resume the download after an app restart. The directory for a local file uri must exist prior to calling this function.
DownloadResumable| Parameter | Type |
|---|---|
| url | string |
| fileUri | string |
| options(optional) | FileSystemUploadOptions |
| callback(optional) | FileSystemNetworkTaskProgressCallback<UploadProgressData> |
UploadTask| Parameter | Type | Description |
|---|---|---|
| fileUri | string |
|
| options(optional) | DeletingOptions | A map of write options represented by Default: {} |
Delete a file or directory. If the URI points to a directory, the directory and all its contents are recursively deleted.
Promise<void>Promise<void>| Parameter | Type | Description |
|---|---|---|
| uri | string | The remote URI to download from. |
| fileUri | string | The local URI of the file to download to. If there is no file at this URI, a new one is created. If there is a file at this URI, its contents are replaced. The directory for the file must exist. |
| options(optional) | DownloadOptions | A map of download options represented by Default: {} |
Download the contents at a remote URI to a file in the app's file system. The directory for a local file uri must exist prior to calling this function.
Promise<FileSystemDownloadResult>Returns a Promise that resolves to a FileSystemDownloadResult object.
Example
FileSystem.downloadAsync( 'http://techslides.com/demos/sample-videos/small.mp4', FileSystem.documentDirectory + 'small.mp4' ) .then(({ uri }) => { console.log('Finished downloading to ', uri); }) .catch(error => { console.error(error); });
| Parameter | Type | Description |
|---|---|---|
| fileUri | string | The local URI of the file. If there is no file at this URI, an exception will be thrown. |
Takes a file:// URI and converts it into content URI (content://) so that it can be accessed by other applications outside of Expo.
Promise<string>Returns a Promise that resolves to a string containing a content:// URI pointing to the file.
The URI is the same as the fileUri input parameter but in a different format.
Example
FileSystem.getContentUriAsync(uri).then(cUri => { console.log(cUri); IntentLauncher.startActivityAsync('android.intent.action.VIEW', { data: cUri, flags: 1, }); });
Gets the available internal disk storage size, in bytes. This returns the free space on the data partition that hosts all of the internal storage for all apps on the device.
Promise<number>Returns a Promise that resolves to the number of bytes available on the internal disk.
| Parameter | Type | Description |
|---|---|---|
| fileUri | string | URI to the file or directory. See supported URI schemes. |
| options(optional) | InfoOptions | A map of options represented by Default: {} |
Gets total internal disk storage size, in bytes. This is the total capacity of the data partition that hosts all the internal storage for all apps on the device.
Promise<number>Returns a Promise that resolves to a number that specifies the total internal disk storage capacity in bytes.
| Parameter | Type | Description |
|---|---|---|
| fileUri | string |
|
| options(optional) | MakeDirectoryOptions | A map of create directory options represented by Default: {} |
Create a new empty directory.
Promise<void>| Parameter | Type | Description |
|---|---|---|
| options | RelocatingOptions | A map of move options represented by |
Move a file or directory to a new location.
Promise<void>| Parameter | Type | Description |
|---|---|---|
| fileUri | string |
|
| options(optional) | ReadingOptions | A map of read options represented by Default: {} |
Read the entire contents of a file as a string. Binary will be returned in raw format, you will need to append data:image/png;base64, to use it as Base64.
Promise<string>A Promise that resolves to a string containing the entire contents of the file.
| Parameter | Type | Description |
|---|---|---|
| fileUri | string |
|
Enumerate the contents of a directory.
Promise<string[]>A Promise that resolves to an array of strings, each containing the name of a file or directory contained in the directory at fileUri.
| Parameter | Type | Description |
|---|---|---|
| url | string | The remote URL, where the file will be sent. |
| fileUri | string | The local URI of the file to send. The file must exist. |
| options(optional) | FileSystemUploadOptions | A map of download options represented by Default: {} |
Upload the contents of the file pointed by fileUri to the remote url.
Promise<FileSystemUploadResult>Returns a Promise that resolves to FileSystemUploadResult object.
Example
Client
import * as FileSystem from 'expo-file-system/legacy'; try { const response = await FileSystem.uploadAsync(`http://192.168.0.1:1234/binary-upload`, fileUri, { fieldName: 'file', httpMethod: 'PATCH', uploadType: FileSystem.FileSystemUploadType.BINARY_CONTENT, }); console.log(JSON.stringify(response, null, 4)); } catch (error) { console.log(error); }
Server
Refer to the "Server: Handling multipart requests" example - there is code for a simple Node.js server.
| Parameter | Type | Description |
|---|---|---|
| fileUri | string |
|
| contents | string | The string to replace the contents of the file with. |
| options(optional) | WritingOptions | A map of write options represented by Default: {} |
Write the entire contents of a file as a string.
Promise<void>Namespaces
The StorageAccessFramework is a namespace inside of the expo-file-system module, which encapsulates all functions which can be used with SAF URIs.
You can read more about SAF in the Android documentation.
Example
Basic Usage
import { StorageAccessFramework } from 'expo-file-system'; // Requests permissions for external directory const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(); if (permissions.granted) { // Gets SAF URI from response const uri = permissions.directoryUri; // Gets all files inside of selected directory const files = await StorageAccessFramework.readDirectoryAsync(uri); alert(`Files inside ${uri}:\n\n${JSON.stringify(files)}`); }
Migrating an album
import * as MediaLibrary from 'expo-media-library'; import * as FileSystem from 'expo-file-system/legacy'; const { StorageAccessFramework } = FileSystem; async function migrateAlbum(albumName: string) { // Gets SAF URI to the album const albumUri = StorageAccessFramework.getUriForDirectoryInRoot(albumName); // Requests permissions const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(albumUri); if (!permissions.granted) { return; } const permittedUri = permissions.directoryUri; // Checks if users selected the correct folder if (!permittedUri.includes(albumName)) { return; } const mediaLibraryPermissions = await MediaLibrary.requestPermissionsAsync(); if (!mediaLibraryPermissions.granted) { return; } // Moves files from external storage to internal storage await StorageAccessFramework.moveAsync({ from: permittedUri, to: FileSystem.documentDirectory!, }); const outputDir = FileSystem.documentDirectory! + albumName; const migratedFiles = await FileSystem.readDirectoryAsync(outputDir); // Creates assets from local files const [newAlbumCreator, ...assets] = await Promise.all( migratedFiles.map<Promise<MediaLibrary.Asset>>( async fileName => await MediaLibrary.createAssetAsync(outputDir + '/' + fileName) ) ); // Album was empty if (!newAlbumCreator) { return; } // Creates a new album in the scoped directory const newAlbum = await MediaLibrary.createAlbumAsync(albumName, newAlbumCreator, false); if (assets.length) { await MediaLibrary.addAssetsToAlbumAsync(assets, newAlbum, false); } }
StorageAccessFramework Methods
| Parameter | Type | Description |
|---|---|---|
| parentUri | string | The SAF URI to the parent directory. |
| fileName | string | The name of new file without the extension. |
| mimeType | string | The MIME type of new file. |
| Parameter | Type | Description |
|---|---|---|
| folderName | string | The name of the folder which is located in the Android root directory. |
Gets a SAF URI pointing to a folder in the Android root directory. You can use this function to get URI for
StorageAccessFramework.requestDirectoryPermissionsAsync() when you trying to migrate an album. In that case, the name of the album is the folder name.
stringReturns a SAF URI to a folder.
| Parameter | Type | Description |
|---|---|---|
| parentUri | string | The SAF URI to the parent directory. |
| dirName | string | The name of new directory. |
| Parameter | Type | Description |
|---|---|---|
| dirUri | string | SAF URI to the directory. |
| Parameter | Type | Description |
|---|---|---|
| initialFileUrl(optional) | string | null | The SAF URI of the directory that the file picker should display when it first loads. If URI is incorrect or points to a non-existing folder, it's ignored. Default: null |
Allows users to select a specific directory, granting your app access to all of the files and sub-directories within that directory.
Returns a Promise that resolves to FileSystemRequestDirectoryPermissionsResult object.
Types
| Property | Type | Description |
|---|---|---|
| idempotent(optional) | boolean | If Default: false |
| Property | Type | Description |
|---|---|---|
| cache(optional) | boolean | - |
| headers(optional) | Record<string, string> | An object containing all the HTTP header fields and their values for the download network request. The keys and values of the object are the header names and values respectively. |
| md5(optional) | boolean | If Default: false |
| sessionType(optional) | FileSystemSessionType | Only for: iOS A session type. Determines if tasks can be handled in the background. On Android, sessions always work in the background and you can't change it. Default: FileSystemSessionType.BACKGROUND |
| Property | Type | Description |
|---|---|---|
| fileUri | string | The local URI of the file to download to. If there is no file at this URI, a new one is created. If there is a file at this URI, its contents are replaced. |
| options | DownloadOptions | Object representing the file download options. |
| resumeData(optional) | string | The string which allows the API to resume a paused download. |
| url | string | The remote URI to download from. |
Deprecated: use
FileSystemNetworkTaskProgressCallback<DownloadProgressData>instead.
Type: FileSystemNetworkTaskProgressCallback<DownloadProgressData>
| Property | Type | Description |
|---|---|---|
| totalBytesExpectedToWrite | number | The total bytes expected to be written by the download operation. A value of |
| totalBytesWritten | number | The total bytes written by the download operation. |
Deprecated: Use
FileSystemDownloadResultinstead.
Type: FileSystemDownloadResult
Type: object shaped as below:
| Property | Type | Description |
|---|---|---|
| exists | true | Signifies that the requested file exist. |
| isDirectory | boolean | Boolean set to |
| md5(optional) | string | Present if the |
| modificationTime | number | The last modification time of the file expressed in seconds since epoch. |
| size | number | The size of the file in bytes. |
| uri | string | A URI pointing to the file. This is the same as the |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| exists | false | - |
| isDirectory | false | - |
| uri | string | - |
Literal Type: string
Acceptable values are: 'POST' | 'PUT' | 'PATCH'
Type: FileSystemHttpResult extended by:
| Property | Type | Description |
|---|---|---|
| md5(optional) | string | Present if the |
| uri | string | A |
| Property | Type | Description |
|---|---|---|
| headers | Record<string, string> | An object containing all the HTTP response header fields and their values for the download network request. The keys and values of the object are the header names and values respectively. |
| mimeType | string | null | - |
| status | number | The HTTP response status code for the download network request. |
Type: object shaped as below:
| Property | Type | Description |
|---|---|---|
| granted | false | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| directoryUri | string | The SAF URI to the user's selected directory. Available only if permissions were granted. |
| granted | true | - |
Type: UploadOptionsBinary | UploadOptionsMultipart extended by:
| Property | Type | Description |
|---|---|---|
| headers(optional) | Record<string, string> | An object containing all the HTTP header fields and their values for the upload network request. The keys and values of the object are the header names and values respectively. |
| httpMethod(optional) | FileSystemAcceptedUploadHttpMethod | The request method. Default: FileSystemAcceptedUploadHttpMethod.POST |
| sessionType(optional) | FileSystemSessionType | Only for: iOS A session type. Determines if tasks can be handled in the background. On Android, sessions always work in the background and you can't change it. Default: FileSystemSessionType.BACKGROUND |
Type: FileSystemHttpResult extended by:
| Property | Type | Description |
|---|---|---|
| body | string | The body of the server response. |
| Property | Type | Description |
|---|---|---|
| md5(optional) | boolean | Whether to return the MD5 hash of the file. Default: false |
| Property | Type | Description |
|---|---|---|
| intermediates(optional) | boolean | If Default: false |
| Property | Type | Description |
|---|---|---|
| encoding(optional) | EncodingType | 'utf8' | 'base64' | The encoding format to use when reading the file. Default: EncodingType.UTF8 |
| length(optional) | number | Optional number of bytes to read. This option is only used when |
| position(optional) | number | Optional number of bytes to skip. This option is only used when |
| Property | Type | Description |
|---|---|---|
| from | string | URI or SAF URI to the asset, file, or directory. See supported URI schemes. |
| to | string |
|
Upload options when upload type is set to binary.
| Property | Type | Description |
|---|---|---|
| uploadType(optional) | FileSystemUploadType | Upload type determines how the file will be sent to the server.
Value will be |
Upload options when upload type is set to multipart.
| Property | Type | Description |
|---|---|---|
| fieldName(optional) | string | The name of the field which will hold uploaded file. Defaults to the file name without an extension. |
| mimeType(optional) | string | The MIME type of the provided file. If not provided, the module will try to guess it based on the extension. |
| parameters(optional) | Record<string, string> | Additional form properties. They will be located in the request body. |
| uploadType | FileSystemUploadType | Upload type determines how the file will be sent to the server.
Value will be |
| Property | Type | Description |
|---|---|---|
| totalBytesExpectedToSend | number | The total bytes expected to be sent by the upload operation. |
| totalBytesSent | number | The total bytes sent by the upload operation. |
| Property | Type | Description |
|---|---|---|
| append(optional) | boolean | Whether to append the contents to the end of the file or overwrite the existing file. Default: false |
| encoding(optional) | EncodingType | 'utf8' | 'base64' | The encoding format to use when writing the file. Default: FileSystem.EncodingType.UTF8 |
Enums
These values can be used to define how file system data is read / written.
These values can be used to define how sessions work on iOS.
FileSystemSessionType.BACKGROUND = 0Using this mode means that the downloading/uploading session on the native side will work even if the application is moved to background. If the task completes while the application is in background, the Promise will be either resolved immediately or (if the application execution has already been stopped) once the app is moved to foreground again.
Note: The background session doesn't fail if the server or your connection is down. Rather, it continues retrying until the task succeeds or is canceled manually.
FileSystemUploadType.BINARY_CONTENT = 0The file will be sent as a request's body. The request can't contain additional data.
FileSystemUploadType.MULTIPART = 1An RFC 2387-compliant request body. The provided file will be encoded into HTTP request.
This request can contain additional data represented by UploadOptionsMultipart type.
支持的 URI scheme
在此表中,你可以看到每种方法可以处理哪种类型的 URI。例如,如果你有一个以 content:// 开头的 URI,就不能使用 FileSystem.readAsStringAsync(),但可以使用支持该 scheme 的 FileSystem.copyAsync()。
| 方法名称 | Android | iOS |
|---|---|---|
getInfoAsync | file:///,content://,asset://,无 scheme | file://,ph://,assets-library:// |
readAsStringAsync | file:///,asset://,SAF URI | file:// |
writeAsStringAsync | file:///,SAF URI | file:// |
deleteAsync | file:///,SAF URI | file:// |
moveAsync | 来源:file:///,SAF URI 目标: file:// | 来源:file://目标: file:// |
copyAsync | 来源:file:///,content://,asset://,SAF URI, 无 scheme 目标: file:// | 来源:file://,ph://,assets-library://目标: file:// |
makeDirectoryAsync | file:/// | file:// |
readDirectoryAsync | file:/// | file:// |
downloadAsync | 来源:http://,https://目标: file:/// | 来源:http://,https://目标: file:// |
uploadAsync | 来源:file:///目标: http://https:// | 来源:file://目标: http://https:// |
createDownloadResumable | 来源:http://,https://目标: file:/// | 来源:http://,https://目标: file:// |
在 Android 上,无 scheme 默认表示一个捆绑资源。
权限
Android
以下权限会通过此库的 AndroidManifest.xml 自动添加。
| Android Permission | Description |
|---|---|
Allows an application to read from external storage. | |
Allows an application to write to external storage. | |
Allows applications to open network sockets. |
iOS
不需要权限。