提交 84947dca 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 028fdcb7
# File Management
- MediaLibrary Management
- [MediaLibrary Overview](medialibrary-overview.md)
- [Media Asset Management](medialibrary-resource-guidelines.md)
- [File Path Management](medialibrary-filepath-guidelines.md)
- [Album Management](medialibrary-album-guidelines.md)
# File
- File Access Framework
- [File Access Framework Overview](file-access-framework-overview.md)
- [FilePicker Guide](filepicker-guidelines.md)
\ No newline at end of file
- [File Management Overview](file-management-overview.md)
- Application File
- [Application File Overview](app-file-overview.md)
- [Application Sandbox Directory](app-sandbox-directory.md)
- Application File Access and Management
- [Accessing Application Files](app-file-access.md)
- [Uploading and Downloading Application Files](app-file-upload-download.md)
- [Obtaining Application and File System Space Statistics](app-fs-space-statistics.md)
- [Sending Files to an Application Sandbox](send-file-to-app-sandbox.md)
- [Sharing an Application File](share-app-file.md)
- User File
- [User File Overview](user-file-overview.md)
- Selecting and Saving User Files (FilePicker)
- [Selecting User Files](select-user-file.md)
- [Saving User Files](save-user-file.md)
- [Developing a FileManager Application (Available Only for System Applications)](dev-user-file-manager.md)
- [Managing External Storage Devices (Available Only for System Applications)](manage-external-storage.md)
- Distributed File System
- [Distributed File System Overview](distributed-fs-overview.md)
- [Setting the Security Level of a Distributed File](set-security-label.md)
- [Access Files Across Devices](file-access-across-devices.md)
# Accessing Application Files
This topic describes how to view, create, read, write, delete, move, or copy a file in the application file directory and obtain the file information.
## Available APIs
You can use [ohos.file.fs](../reference/apis/js-apis-file-fs.md) to implement the application file access capabilities. The following table describes the APIs.
**Table 1** APIs for basic application file operations
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| -------- | -------- | -------- | -------- | -------- |
| access | Checks whether a file exists.| Method| √ | √ |
| close | Closes a file.| Method| √ | √ |
| copyFile | Copies a file.| Method| √ | √ |
| createStream | Creates a stream based on the specified file path.| Method| √ | √ |
| listFile | Lists all files in a directory.| Method| √ | √ |
| mkdir | Creates a directory.| Method| √ | √ |
| moveFile | Moves a file.| Method| √ | √ |
| open | Opens a file.| Method| √ | √ |
| read | Reads data from a file.| Method| √ | √ |
| rename | Renames a file or folder.| Method| √ | √ |
| rmdir | Deletes a directory.| Method| √ | √ |
| stat | Obtains detailed file information.| Method| √ | √ |
| unlink | Deletes a single file.| Method| √ | √ |
| write | Writes data to a file.| Method| √ | √ |
| Stream.close | Closes a stream.| Method| √ | √ |
| Stream.flush | Flushes all data from this stream.| Method| √ | √ |
| Stream.write | Writes data to a stream.| Method| √ | √ |
| Stream.read | Reads data from a stream.| Method| √ | √ |
| File.fd | Defines a file descriptor.| Attribute| √ | × |
| OpenMode | Defines the mode for opening a file.| Attribute| √ | × |
| Filter | Defines the options for setting the file filter.| Type| × | × |
## Development Example
Obtain the [application file path](../application-models/application-context-stage.md#obtaining-the-application-development-path). The following example shows how to obtain a HAP file path using **UIAbilityContext**. For details about how to obtain **UIAbilityContext**, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
The following describes common file operations.
### Creating, Reading, and Writing a File
The following example demonstrates how to create a file, read data from it, and write data to it.
```ts
// pages/xxx.ets
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
function createFile() {
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
// Create a file and open it.
let file = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// Write data to the file.
let writeLen = fs.writeSync(file.fd, "Try to write str.");
console.info("The length of str is: " + writeLen);
// Read data from the file.
let buf = new ArrayBuffer(1024);
let readLen = fs.readSync(file.fd, buf, { offset: 0 });
console.info("the content of file: " + String.fromCharCode.apply(null, new Uint8Array(buf.slice(0, readLen))));
// Close the file.
fs.closeSync(file);
}
```
### Copying Data to Another File
The following example demonstrates how to write the data read from a file to another file.
```ts
// pages/xxx.ets
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
function readWriteFile() {
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
// Open the source and destination files.
let srcFile = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE);
let destFile = fs.openSync(filesDir + '/destFile.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// Read data from the source file and copy it to the destination file.
let bufSize = 4096;
let readSize = 0;
let buf = new ArrayBuffer(bufSize);
let readLen = fs.readSync(srcFile.fd, buf, { offset: readSize });
while (readLen > 0) {
readSize += readLen;
fs.writeSync(destFile.fd, buf);
readLen = fs.readSync(srcFile.fd, buf, { offset: readSize });
}
// Close the files.
fs.closeSync(srcFile);
fs.closeSync(destFile);
}
```
> **NOTE**
>
> When using **read()** or **write()**, pay attention to the optional parameter **offset**. For a file that has been read or written, the offset pointer is at the end position of the last read or write operation by default.
### Reading and Writing Files in a Stream
The following example demonstrates how to read and write file data using a stream.
```ts
// pages/xxx.ets
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
async function readWriteFileWithStream() {
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
// Open the file streams.
let inputStream = fs.createStreamSync(filesDir + '/test.txt', 'r+');
let outputStream = fs.createStreamSync(filesDir + '/destFile.txt', "w+");
// Read data from the source file and write the data to the destination file using a stream.
let bufSize = 4096;
let readSize = 0;
let buf = new ArrayBuffer(bufSize);
let readLen = await inputStream.read(buf, { offset: readSize });
readSize += readLen;
while (readLen > 0) {
await outputStream.write(buf);
readLen = await inputStream.read(buf, { offset: readSize });
readSize += readLen;
}
// Close the streams.
inputStream.closeSync();
outputStream.closeSync();
}
```
> **NOTE**
>
> Close the stream that is no longer used in a timely manner. <br>Comply with the related programming specifications for **Stream** APIs in asynchronous mode and avoid mixed use of the APIs in synchronous mode and asynchronous mode. <br>The **Stream** APIs do not support concurrent read and write operations.
### Listing Files
The following example demonstrates how to list files.
```ts
// List files.
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
// List files that meet the specified conditions.
let options = {
recursion: false,
listNum: 0,
filter: {
suffix: ['.png', '.jpg', '.txt'], // The filename extension can be '.png', '.jpg', or '.txt'.
displayName: ['test%'], // The filename starts with 'test'.
fileSizeOver: 0, // The file size is greater than or equal to 0.
lastModifiedAfter: new Date(0).getTime(), // The latest modification time of the file is later than January 1, 1970.
},
}
let files = fs.listFileSync(filesDir, options);
for (let i = 0; i < files.length; i++) {
console.info(`The name of file: ${files[i]}`);
}
```
# Application File Overview
Application files are files of an application, including the application's installation files, resource files, and cache files.
- The data used and saved by an application is stored in files, key-value (KV) pairs, and databases in a dedicated directory on a device. This directory is called application file directory, and the files in the directory are application files.
- The directories visible to an application include the application file directory and a directory containing the minimum system files required for the running of the application. These two directories constitute an [application sandbox directory](app-sandbox-directory.md). That means, the application file directory is a subset of the application sandbox directory.
- The system files and directories are read-only for the application. The application can only save files to sub-directories in the [application file directory](app-sandbox-directory.md#application-file-directory-and-application-file-path) based on certain rules.
The following topics describe the application sandbox, application file directories, and how to access, manage, and share application files.
# Uploading and Downloading an Application File
This topic describes how to upload an application file to a network server and download a network resource file from a network server to a local application directory.
## Uploading an Application File
You can use [ohos.request](../reference/apis/js-apis-request.md) **uploadFile()** to upload local files. The system service proxy implements the upload.
> **NOTE**
>
> Currently, only the files in the **cache/** directories (**cacheDir**) can be uploaded.
>
> <br>The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
The following example demonstrates how to upload a file in the **cache** directory of an application to a network server.
```ts
// pages/xxx.ets
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import request from '@ohos.request';
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let cacheDir = context.cacheDir;
// Create an application file locally.
let file = fs.openSync(cacheDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.writeSync(file.fd, 'upload file test');
fs.closeSync(file);
// Configure the upload task.
let uploadConfig = {
url: 'https://xxx',
header: { key1: 'value1', key2: 'value2' },
method: 'POST',
files: [
{ filename: 'test.txt', name: 'test', uri: 'internal://cache/test.txt', type: 'txt' }
],
data: [
{ name: 'name', value: 'value' }
]
}
// Upload the created application file to the network server.
try {
request.uploadFile(context, uploadConfig)
.then((uploadTask) => {
uploadTask.on('complete', (taskStates) => {
for (let i = 0; i < taskStates.length; i++) {
console.info(`upload complete taskState: ${JSON.stringify(taskStates[i])}');
}
});
})
.catch((err) => {
console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`);
})
} catch (err) {
console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`);
}
```
## Downloading a Network Resource File to the Application File Directory
You can use [ohos.request](../reference/apis/js-apis-request.md) **downloadFile()** to download network resource files to a local application directory. You can use the ([ohos.file.fs](../reference/apis/js-apis-file-fs.md) APIs to access the downloaded files. For details, see [Accessing Application Files](app-file-access.md). The system service proxy implements the download.
> **NOTE**
>
> Currently, network resource files can be downloaded only to an application file directory.
>
> <br>The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
The following example demonstrates how to download a network resource file to a local application file directory.
```ts
// pages/xxx.ets
// Download the network resource file to the local application file directory, and read data from the file.
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import request from '@ohos.request';
// Obtain the application file path.
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
try {
request.downloadFile(context, {
url: 'https://xxxx/xxxx.txt',
filePath: filesDir + '/xxxx.txt'
}).then((downloadTask) => {
downloadTask.on('complete', () => {
console.info('download complete');
let file = fs.openSync(filesDir + '/xxxx.txt', fs.OpenMode.READ_WRITE);
let buf = new ArrayBuffer(1024);
let readLen = fs.readSync(file.fd, buf);
console.info(`The content of file: ${String.fromCharCode.apply(null, new Uint8Array(buf.slice(0, readLen)))}`);
fs.closeSync(file);
})
}).catch((err) => {
console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);
});
} catch (err) {
console.error(`Invoke downloadFile failed, code is ${err.code}, message is ${err.message}`);
}
```
# Obtaining Application and File System Space Statistics
This topic describes how to obtain information about the free system space and space occupied by applications so as to prevent insufficient storage space of the system or ensure proper use of quota-controlled **cacheDir** directories.
## Available APIs
For details about the APIs, see [ohos.file.statvfs](../reference/apis/js-apis-file-statvfs.md) and [ohos.file.storageStatistics](../reference/apis/js-apis-file-storage-statistics.md).
**Table 1** APIs for file system and application space statistics
| Module| API| Description|
| -------- | -------- | -------- |
| \@ohos.file.storageStatistic | getCurrentBundleStats | Obtains the storage space of the current application, in bytes.|
| \@ohos.file.statvfs | getFreeSize | Obtains the free space of a file system, in bytes.|
| \@ohos.file.statvfs | getTotalSize | Obtains the total space of a file system, in bytes.|
**Table 2** Attributes for application space statistics
| BundleStats Attribute| Description| Directory for Statistics|
| -------- | -------- | -------- |
| appSize | Size of the application installation files, in bytes.| Application installation file directory:<br>**/data/storage/el1/bundle **|
| cacheSize | Size of the application cache files, in bytes.| Application cache file directories:<br>**/data/storage/el1/base/cache**<br>**/data/storage/el1/base/haps/entry/cache**<br>**/data/storage/el2/base/cache**<br>**/data/storage/el2/base/haps/entry/cache **|
| dataSize | Size of the application files (excluding the application installation files and cache files), in bytes.| The application files include local files, distributed files, and database files.<br>- Local application file directories (parent directories of the **cache** directories):<br>**/data/storage/el1/base**<br>**/data/storage/el2/base**<br>- Distributed application directory:<br>/data/storage/el2/distributedfiles<br>- Database directories:<br>**/data/storage/el1/database**<br>**/data/storage/el2/database **|
## Development Example
- Obtain the free space of **/data** of the file system.
```ts
import statvfs from '@ohos.file.statvfs';
let path = "/data";
statvfs.getFreeSize(path, (err, number) => {
if (err) {
console.error(`Invoke getFreeSize failed, code is ${err.code}, message is ${err.message}`);
} else {
console.info(`Invoke getFreeSize succeeded, size is ${number}`);
}
});
```
- Obtain the space occupied by the current application.
```ts
import storageStatistics from "@ohos.file.storageStatistics";
storageStatistics.getCurrentBundleStats((err, bundleStats) => {
if (err) {
console.error(`Invoke getCurrentBundleStats failed, code is ${err.code}, message is ${err.message}`);
} else {
console.info(`Invoke getCurrentBundleStats succeeded, appsize is ${bundleStats.appSize}`);
}
});
```
# Application Sandbox Directory
The application sandbox is an isolation mechanism to prevent data from being accessed through path traversal. This mechanism allows only the application sandbox directory visible to an application.
- The system maps a dedicated application sandbox directory in the internal storage space for each application. The directory is a collection of the [application file directory](app-file-overview.md) and a directory containing the minimum system files required during application's runtime.
- The application sandbox specifies the minimum range of data visible to each application. In the application sandbox directory, an application can access only its own application files and the system files required for its running. The application cannot access files of other applications. The security of application files is protected in this way.
- In each application sandbox directory, the application can save and process its own application files in the [application file directory](app-file-overview.md), and can only read the system files and directories. The application can access [user files](user-file-overview.md) by using specific APIs only with authorization from the user.
The following figure illustrates the file access scope and modes for an application in an application sandbox.
**Figure 1** File access in an application sandbox
![Application sandbox file access relationship](figures/application-sandbox-file-access-relationship.png)
## Application Sandbox Directory and Application Sandbox Path
With the application sandbox mechanism, an application cannot learn the location and existence of other applications' directories and user file directories. In addition, all the application directories visible to an application are isolated by permission and namespace to form an independent directory view and shield the real (physical) paths.
- As shown in the following figure, the sandbox mechanism minimizes the number of directories and files visible to a common application (third-party application). The directories and file paths visible to a common application are different from those visible to a system process. The path of a file or folder in the application sandbox directory visible to a common application is called the application sandbox path.
- You can view the real application paths (the directory view visible to a system process) in the HDC shell environment. For details about the mappings between the application sandbox paths and real application paths, see [Mappings Between Application Sandbox Paths and Physical Paths](send-file-to-app-sandbox.md#mappings-between-application-sandbox-paths-and-physical-paths).
- The application sandbox paths and physical paths are not in one-to-one mappings. The application sandbox paths are always less than the physical paths. You may not obtain the the application sandbox path based on a physical path in certain cases, but you can obtain the physical path based on an application sandbox path.
**Figure 2** Different directory views to processes and applications
![Application sandbox path](figures/application-sandbox-path.png)
## Application File Directory and Application File Path
The application sandbox directory includes application file directories and system file directories.
The system file directories visible to an application are preset by OpenHarmony.
The following figure shows the application file directories. The path of a file or a folder in the application file directory is called the application file path. The file paths in the application file directory have different attributes and characteristics.
**Figure 3** Application file directory structure
![Application file directory structure](figures/application-file-directory-structure.png)
1. Level 1 directory **data/**: indicates the application file directory.
2. Level 2 directory **storage/**: indicates a directory for persistent files of the application.
3. Level 3 directories **el1/** and **el2/**: indicate directories for files of different encryption levels (els).
- **el1**: directory for the data that can be accessed once the device starts. This directory contains device-focused files.
- **el2**: directory for the data that can be accessed only after at lease one successful unlocking operation (by PIN, fingerprint, or facial authentication, or password-free sign-in) upon the start of the device. This directory contains user-focused files.<br>
Unless otherwise required, application data is placed in the **el2** directory for security purposes. However, the data that needs to be accessed before the screen is unlocked (such as the clock, alarm, and wallpaper data) can be placed in the **el1** directory. For details about how to switch to and modify the **el** directories, see [Obtaining and Modifying el Directories](../application-models/application-context-stage.md#obtaining-and-modifying-encryption-areas).
4. Level 4 and level 5 directories:
The application's global data is stored in the **files**, **cache**, **preferences**, **temp**, and **distributedfiles** folders in **base**. You can use **ApplicationContext** to obtain the application file paths of these folders.
You can use **UIAbilityContext**, **AbilityStageContext**, and **ExtensionContext** to obtain application file paths related to the OpenHarmoy Ability Package (HAP). When the HAP is uninstalled, the files stored in these directories are automatically deleted, without affecting the files in app-level directories. An application in the development state contains one or more HAPs. For details, see [Application Package Structure in Stage Mode](../quick-start/application-package-structure-stage.md).
For details about how to obtain the context and application file paths, see [Context (Stage Model)](../application-models/application-context-stage.md).
> **NOTE**
>
> - Do not directly use file paths made up by level 1 to level 4 directory names. Incompatibility problems may occur if the directory names are changed in later versions.
> - Use **Context** to obtain application file paths, which include but are not limited to the directories highlighted in green in **Figure 3**.
The following table describes the application file paths and lifecycle.
**Table 1** Application file paths
| Folder| Context Attribute Name| Type| Description|
| -------- | -------- | -------- | -------- |
| bundle | bundleCodeDir | Installation file directory| Directory for saving the HAPs of the application after an application is installed.<br>This directory is cleared when the application is uninstalled.<br> Do not access resource files by concatenating paths. Use [@ohos.resourceManager] instead.|
| base | NA | Directory for local device files| Directory for saving the application's persistent data on the device. Subdirectories include **files/**,** cache/**, **temp/**, and **haps/**.<br>This directory is cleared when the application is uninstalled.|
| database | databaseDir | Database directory| Directory in **el1** for saving the files operated by the distributed database service.<br>This directory is cleared when the application is uninstalled.|
| distributedfiles | distributedFilesDir | Distributed file directory| Directory in **el2** for saving the application files that can be directly accessed across devices.<br>This directory is cleared when the application is uninstalled.|
| files | filesDir | Application file directory| Directory for saving the application's persistent files on the device.<br>This directory is cleared when the application is uninstalled.|
| cache | cacheDir | Application cache file directory| Directory for caching the downloaded files of the application or saving the cache files regenerated on the device.<br>This directory is automatically cleared when the size of the **cache** directory reaches the quota or the system storage space reaches a certain threshold. The user can also clear this directory by using a system space management application. <br>The application needs to check whether the file still exists and determine whether to cache the file again.|
| preferences | preferencesDir | Preferences file directory| Directory for saving common application configuration and user preference data managed by using database APIs.<br>This directory is cleared when the application is uninstalled. For details, see [Data Persistence by User Preferences](../database/data-persistence-by-preferences.md).|
| temp | tempDir | Temporary file directory| Directory for saving the files generated and required during the application's runtime on the device. <br>This directory is cleared when the application exits.|
The application file paths are used in the following scenarios:
- Installation file directory<br>
Used to store the code resource data of the application, including the HAPs of the application, reusable library files, and plug-ins. The code stored in this directory can be dynamically loaded.
- Database directory<br>
Used to store only the application's private database data, such as database files. This directory can be used to store distributed database data only.
- Distributed file directory<br>
Used to store the application's data used for distributed scenarios, including file sharing, file backup, and file processing across devices. The data stored in this directory enables the application to run smoothly on multiple devices.
- Application file directory<br>
Used to store private data of the application, including persistent files, images, media files, and log files. The data is stored in this directory to ensure privacy, security, and permanent validity.
- Cached application file directory<br>
Used to store cached data of the application, including offline data, cached images, database backup, and temporary files. Data stored in this directory may be automatically deleted by the system. Therefore, do not store important data in this directory.
- Preferences file directory<br>
Used to store application preferences data, including preference files and configuration files. This directory applied to storing only a small amount of data.
- Temporary file directory<br>
Used to store temporarily generated data of an application, including cached database data and images, temporary log files, downloaded application installation package files. The data stored in this directory is deleted after being used.
<!--no_check-->
\ No newline at end of file
# Developing a FileManager Application (Available Only for System Applications)
OpenHarmony is prebuilt with the **FileManager** application. You can also develop your own **FileManager** as required.
## Available APIs
For details about the APIs, see [User File Access and Management](../reference/apis/js-apis-fileAccess.md).
## How to Develop
1. Configure the permissions required and import dependent modules.
Apply for the **ohos.permission.FILE_ACCESS_MANAGER** and **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** permissions. For details, see [Applying for Permissions](../security/accesstoken-guidelines.md).
> **NOTE**
>
> **ohos.permission.FILE_ACCESS_MANAGER** is required for using the user file access framework APIs.
>
> **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** is required for querying information about file management server applications supported by the system.
2. Import the dependent modules.
```ts
import fileAccess from '@ohos.file.fileAccess';
import fileExtensionInfo from '@ohos.file.fileExtensionInfo';
```
The **fileAccess** module provides APIs for basic file operations, and the **fileExtensionInfo** module provides key structs for application development.
3. Query device information.
You can obtain attributes of one or all devices managed by the file management server in the current system. You can also filter devices as required.
In the user file access framework, **RootInfo** indicates the attribute information of a device. For example, obtain **RootInfo** of all devices.
```ts
// Create a helper object for connecting to all file management servers in the system.
let fileAccessHelperAllServer = null;
createFileAccessHelper() {
try { // this.context is the context passed from EntryAbility.
fileAccessHelperAllServer = fileAccess.createFileAccessHelper(this.context);
if (!fileAccessHelperAllServer) {
console.error("createFileAccessHelper interface returns an undefined object");
}
} catch (error) {
console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
}
}
async getRoots() {
let rootIterator = null;
let rootInfos = [];
let isDone = false;
try {
rootIterator = await fileAccessHelperAllServer.getRoots();
if (!rootIterator) {
console.error("getRoots interface returns an undefined object");
return;
}
while (!isDone) {
let result = rootIterator.next();
console.info("next result = " + JSON.stringify(result));
isDone = result.done;
if (!isDone)
rootinfos.push(result.value);
}
} catch (error) {
console.error("getRoots failed, errCode:" + error.code + ", errMessage:" + error.message);
}
}
```
4. View directories.
In the user file access framework, **FileInfo** indicates basic information about a file (directory). You can use **listfile()** to traverse all files (directories) of the next level to obtain a **FileIterator** object or use **scanfile()** to filter the specified directories and obtain the **FileIterator** object that meets the conditions.
Currently, **listfile()** and **scanfile()** can be called by the **RootInfo** object to traverse lower-level files or filter the entire directory tree. In addition, **listfile()** and **scanfile()** can be called by the **FileInfo** object to traverse lower-level files or filter specified directories.
```ts
// Start from the root directory.
let rootInfo = rootinfos[0];
let fileInfos = [];
let isDone = false;
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
try {
let fileIterator = rootInfo.listFile(); // Traverse the root directory of rootinfos[0] and return an iterator object.
// let fileIterator = rootInfo.scanFile(filter); // Filter the file information of device rootinfos[0] that meets the specified conditions and return an iteration object.
if (!fileIterator) {
console.error("listFile interface returns an undefined object");
return;
}
while (!isDone) {
let result = fileIterator.next();
console.info("next result = " + JSON.stringify(result));
isDone = result.done;
if (!isDone)
fileInfos.push(result.value);
}
} catch (error) {
console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
}
// Start from the specified directory.
let fileInfoDir = fileInfos[0]; // fileInfoDir indicates information about a directory.
let subFileInfos = [];
let isDone = false;
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
try {
let fileIterator = fileInfoDir.listFile(); // Traverse files in the specified directory and return an iterator object.
// let fileIterator = rootInfo.scanFile(filter); // Filter the files in the specified directory and return an iterator object.
if (!fileIterator) {
console.error("listFile interface returns an undefined object");
return;
}
while (!isDone) {
let result = fileIterator.next();
console.info("next result = " + JSON.stringify(result));
isDone = result.done;
if (!isDone)
subfileInfos.push(result.value);
}
} catch (error) {
console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
}
```
5. Perform operations on files or directories.
You can integrate APIs of the user file access framework to implement user behaviors, such as deleting, renaming, creating, and moving a file (directory). The following example shows how to create a file. For details about other APIs, see [User File Access and Management](../reference/apis/js-apis-fileAccess.md).
```ts
// The local device is used as an example.
// Create a file.
// sourceUri is the URI in fileinfo of the Download directory.
// You need to use the obtained URI for development.
let sourceUri = "datashare:///media/file/6";
let displayName = "file1";
let fileUri = null;
try {
// Obtain fileAccessHelper by referring to the sample code of fileAccess.createFileAccessHelper.
fileUri = await fileAccessHelper.createFile(sourceUri, displayName);
if (!fileUri) {
console.error("createFile return undefined object");
return;
}
console.info("createFile sucess, fileUri: " + JSON.stringify(fileUri));
} catch (error) {
console.error("createFile failed, errCode:" + error.code + ", errMessage:" + error.message);
};
```
# Distributed File System Overview
OpenHarmony distributed file system (hmdfs) provides cross-device file access capabilities applicable to the following scenarios:
- The user can use the editing software on one device to edit the files on another device.
- Music stored on a tablet can be directly viewed and played by a in-car system.
- The user can use a tablet to view the photos taken by another device.
The hmdfs provides a globally consistent access view for each device dynamically connected to a network via DSoftBus and allows you to implement high-performance read and write operations on files with low latency by using basic file system APIs.
## Distributed File System Architecture
![Distributed File System Architecture](figures/distributed-file-system-architecture.png)
- distributedfile_daemon: listens for device online status, establishes links over DSoftBus, and applies data transfer policies based on the security level of the device.
- hmdfs: implements a network file system in the kernel, providing cache management, file access, metadata management, and conflict management.
- Buffer management
- After devices are connected to form a Virtual Device, hmdfs provides file access capabilities, but does not proactively transmit or copy files. Active copy is required when an application needs to save data to a local directory.
- The hmdfs ensures close-to-open cache consistency, which allows data to flushed when a client closes a file. Then, the latest data can be read when the file is opened on any other client. The hmdfs does not ensure real-time consistency of the file content.
- If data written at the peer end has not been flushed to the local end in a timely manner due to network problems, the file system flushes the data to the local end upon the next network access. However, if the data has been modified on the remote end, only the latest data can be flushed.
- File access
- OpenHarmony provides the same interface, [ohos.file.fs](../reference/apis/js-apis-file-fs.md), for accessing files in the local and distributed file systems.
- The files in the local file system are accessed in overlay mode.
- The files on another device are accessed over a synchronous network.
> **NOTE**
>
> symlink is not supported.
- Metadata management
- In distributed networking, when a file is created, deleted, or modified on a client, the latest file can be viewed on another client. The speed varies depending on the network status.
- If a device goes offline, its data is no longer visible to other devices. However, due to the delay in sensing the device offline, the files of some offline devices may also be visible to other devices. Therefore, you need to consider the network delay in application development.
- Conflict Handling
- If a file on the local end and a file on the remote end have the same name, the file on the remote end will be renamed.
- If multiple remote devices have files of the same name, the name of the file with the smallest device access ID is retained and the files on other devices will be renamed.
- In the networking scenario, the directory tree has remote files. If "duplicate file name" is displayed when a file is created,
- the conflict file is renamed "_conflict_dev_ID". The ID automatically increases from 1.
- If a local directory has the same name as a remote directory, "_remote_directory" will be added to the end of the peer directory.
# Access Files Across Devices
The distributed file system provides cross-device file access capabilities for applications. For the same application installed on multiple devices, you can implement read and write of the files in the application's distributed directory (**/data/storage/el2/distributedfiles/**) across devices by using [ohos.file.fs](app-file-access.md). For example, device A and device B are installed with the same application. After device A and device B are connected to form a Virtual Device, the application on device A can access the files of the same application on Device B. What you need to do is place the files to the distributed directory.
## How to Develop
1. Complete distributed networking for the devices.
Connect the devices to a LAN, and complete authentication of the devices. The devices must have the same account number.
2. Implement cross-device access to the files of the same application.
Place the files in the **distributedfiles/** directory of the application sandbox to implement access from difference devices.
For example, create a test file in the **distributedfiles/** directory on device A and write data to the file. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
```ts
import fs from '@ohos.file.fs';
let context =...; // Obtain the UIAbilityContext information of device A.
let pathDir = context.distributedFilesDir;
// Obtain the file path of the distributed directory.
let filePath = pathDir + '/test.txt';
try {
// Create a file in the distributed directory.
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
console.info('Succeeded in createing.');
// Write data to the file.
fs.writeSync(file.fd, 'content');
// Close the file.
fs.closeSync(file.fd);
} catch (err) {
console.error(`Failed to openSync / writeSync / closeSync. Code: ${err.code}, message: ${err.message}`);
}
```
Read the file on device B.
```ts
import fs from '@ohos.file.fs';
let context =...; // Obtain the UIAbilityContext information of device B.
let pathDir = context.distributedFilesDir;
// Obtain the file path of the distributed directory.
let filePath = pathDir + '/test.txt';
try {
// Open the file in the distributed directory.
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
// Set the buffer for receiving the read data.
let buffer = new ArrayBuffer(4096);
// Read the file. The return value is the number of read bytes.
let num = fs.readSync(file.fd, buffer, {
offset: 0
});
// Print the read data.
console.info('read result: ' + String.fromCharCode.apply(null, new Uint8Array(buffer.slice(0, num))));
} catch (err) {
console.error(`Failed to openSync / readSync. Code: ${err.code}, message: ${err.message}`);
}
```
# File Access Framework Overview
On devices running OpenHarmony 3.2 (API version 9) or later, applications can access public files on the local device, remote device, and external storage device, as well as files shared by multiple users, based on the File Access Framework (FAF).
To ensure user data privacy, this framework allows users to create, open, delete, rename, and move files on the file access server only through the **File Manager** and **File Picker** applications.
The user data of an application is stored on the device even after the application is uninstalled.
If a system application needs to access public files on the local device, use [File Path Management](medialibrary-filepath-guidelines.md).
> **NOTE**
> 1. For a non-management system application, for example, **Gallery**, use the **mediaLibrary** APIs for direct file operation.
> 2. In principle, do not mix use the FAF APIs with the mediaLibrary APIs.
## FAF Mechanism
Based on the OpenHarmony [ExtensionAbility mechanism](../application-models/extensionability-overview.md), the FAF provides unified APIs for external systems. With these APIs, applications can preview and operate public files to implement their own logic.
You can visit the [source repository](https://gitee.com/openharmony/filemanagement_user_file_service) for more details.
The following figure shows the FAF-based file operation process.
**Figure 1** Hierarchy of public file operations
![](figures/public-file-operation.png)
- **File access client**: an application that needs to access or operate public files. By starting the file selector application, it enables users to perform file operations on the UI.
- **File selector application**: a system application that allows users to access all shared datasets. You can use the FAF APIs to operate the datasets.
- **File access server**: a service that supports dataset sharing in the system. Currently, [UserFileManager](https://gitee.com/openharmony/multimedia_medialibrary_standard) and ExternalFileManager are available. UserFileManager manages datasets on local disks and distributed devices, and ExternalFileManager manages datasets on external storage devices such as SD cards and USB flash drives. You can also share your own datasets based on the FAF server configuration.
The FAF has the following features:
- Users can browse the datasets provided by all file server applications in the system, rather than those provided by a single application.
- The file access client can operate files through the file selector application, without obtaining the permission to use the FAF.
- Multiple temporarily mounted devices, such as external storage cards and distributed devices, can be accessed at the same time.
## Data Models
Data models in the FAF are transferred through URI, FileInfo, and RootInfo. For details, see [fileExtension](../reference/apis/js-apis-fileExtensionInfo.md). Applications on the file access server can use the **FileAccessExtensionAbility** APIs to securely share their data.
**Figure 2** Data flow of the public file access framework
![](figures/faf-data-flow.png)
NOTE
- In the FAF, the file access client does not directly interact with the file access server. The client only needs to have the permission to start the file selector application.
- The file selector application provides a standard document access UI for users, even if the underlying file access servers differ greatly.
# File Management Overview
The data in an operating system (OS) can be classified into the following types based on the data structure:
- Structured data: data that can be defined in a unified data model. The structured data is generally stored in a database. In application development, the management of structured data is implemented by the [data management module](../database/data-mgmt-overview.md).
- Unstructured data: data that does not conform to any predefined data structure or model and cannot be easily presented in two-dimensional database tables. Unstructured data includes files in a variety of formats, such as documents, images, videos, and audio clips. In application development, the management of unstructured data is implemented by the file management module, which will be elaborated in this document.
In the file management module, the files can be classified into the following types based on the file owner:
- [Application files](app-file-overview.md): files of an application, including the application's installation files, resource files, and cached files.
- [User files](user-file-overview.md): files of a user who logs in to the device, including the user's images, video and audio clips, and documents.
- System files: files irrelevant to applications and users, including public libraries, device files, and system resource files. System files do not need to be managed by developers and are not described in this document.
The file systems can be classified into the following types based on the file storage location (data source location):
- Local file system: provides capabilities for accessing the files stored on a local device or its external storage devices (such as USB flash drives and removable hard drives). The local file system is the most basic file system and is not described in this document.
- [Distributed file system](distributed-fs-overview.md): provides capabilities for accessing files across devices, which are connected through a computer network.
**Figure 1** Files in an OS
![File classification model](figures/file-classification-model.png)
<!--no_check-->
\ No newline at end of file
# FilePicker Guide
FilePicker is a system application preset in OpenHarmony. You can use it to select and save files. For details about the implementation of FilePicker, see [applications_filepicker](https://gitee.com/openharmony/applications_filepicker).
FilePicker provides the following modes:
- **choose**: Use this mode when an application needs to select and upload or send files (including media resources such as images, and audio and video clips) in the device. When this mode is selected, the FilePicker **choose** mode window will be triggered to display a dialog box for you to select a file. You can select the target file and tap **Upload**. The application will receive the URI of the target file returned by FilePicker.
- **save**: Use this mode when an application needs to download and save files (including media resources such as images and audio and video clips). When this mode is selected, the FilePicker **save** mode window will be triggered to display a dialog box for you to select the destination path of the file to save. You can select the destination path and tap **Save**. The application will receive the URI of the saved file returned by FilePicker.
## Development Guidelines
> **NOTE**
> FilePicker supports only the applications developed based on the stage model.
> For details about the stage model, see [Interpretation of the Application Model](../application-models/application-model-description.md).
You can use [AbilityContext.startAbilityForResult(want, options)](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilityforresult-1) with different parameters to start FilePicker in different modes.
You need to use [Want](../reference/apis/js-apis-application-want.md) to specify **bundleName** and **abilityName** to start FilePicker. For details, see the following sample code.
You also need to set **Want.parameters** to specify the FilePicker mode to start and the name of the file to save.
- To select a file, set **'startMode': 'choose'**.
- To save a file, set **'startMode': 'save'** and **'saveFile'**.
You can set **options** of the [StartOptions](../reference/apis/js-apis-app-ability-startOptions.md) type to specify the dialog box style. The recommended value is **windowMode: 102**, which indicates a floating window.
> **CAUTION**
> - In the **save** mode, a strong verification is performed on the file path based on the name of the file to save. For details about the file path format, see [File Path Management](medialibrary-filepath-guidelines.md).
> - If a file with the same name exists, a dialog box will be displayed asking you whether to overwrite the existing file.
ArkTS sample code:
```ts
// Start FilePicker to select a file.
globalThis.context.startAbilityForResult(
{
action: "ohos.want.action.OPEN_FILE",
parameters: {
'startMode': 'choose', //choose or save
}
},
{ windowMode: 102 }
)
// Start FilePicker to save a file.
globalThis.context.startAbilityForResult(
{
action: "ohos.want.action.CREATE_FILE",
parameters: {
'startMode': 'save', //choose or save
'saveFile': 'test.jpg',
}
},
{ windowMode: 102 }
)
// Data returned by FilePicker to startAbilityForResult.
let abilityResult = {
resultCode: resultCode,
want: {
parameters: {
'startMode': startMode,
'result': result
}
}
}
globalThis.context.terminateSelfWithResult(abilityResult)
```
# Managing External Storage Devices (Available Only for System Applications)
External storage devices are pluggable. OpenHarmony provides the functions of listening for the device insertion and removal events and mounting/unmounting an external storage device.
External storage devices are managed by the StorageManager and StorageDaemon services. StorageDaemon implements the underlying listening and mount/unmount functions. StorageManager provides status change notifications, query, and management capabilities for system applications.
**Figure 1** External storage device management
![External storage device management](figures/external-storage-device-management.png)
- When an external storage device is inserted, the StorageDaemon process obtains an insertion event over netlink and creates a disk device and volume. The created volume is in the **UNMOUNTED** state.
- Then, the StorageDaemon process checks the volume. During the check process, the volume is in the **CHECKING** state.
- The StorageDaemon process mounts the volume if the check is successful. If the mount operation is successful, the volume state changes to **MOUNTED** and StorageManager is instructed to send the COMMON_EVENT_VOLUME_MOUNTED broadcast.
- If the check fails, the volume state changes to **UNMOUNTED**.
- For a volume in the **MOUNTED** state:
- If the device is directly removed, the volume information will be deleted and COMMON_EVENT_VOLUME_BAD_REMOVAL is broadcast.
- If the user chooses **Eject device**, the volume state changes to **EJECTING** and the COMMON_EVENT_VOLUME_EJECT is broadcast. After StorageDaemon unmounts the volume, the volume state changes to **UNMOUNTED** and COMMON_EVENT_VOLUME_UNMOUNTED is broadcast.
- For a volume in the **UNMOUNTED** state, removing the device will delete the volume information and broadcast COMMON_EVENT_VOLUME_REMOVED.
## Available APIs
For details about APIs, see [Volume Management](../reference/apis/js-apis-file-volumemanager.md).
The following table describes the broadcast related parameters.
**Table 1** Broadcast parameters
| Broadcast| Parameter|
| -------- | -------- |
| usual.event.data.VOLUME_REMOVED | **id**: ID of the volume.<br>**diskId**: ID of the disk to which the volume belongs.|
| usual.event.data.VOLUME_UNMOUNTED | **id**: ID of the volume.<br>**diskId**: ID of the disk to which the volume belongs.<br>**volumeState**: state of the volume.|
| usual.event.data.VOLUME_MOUNTED | **id**: ID of the volume.<br>**diskId**: ID of the disk to which the volume belongs.<br>**volumeState**: state of the volume.<br>**fsUuid**: universally unique identifier (UUID) of the volume.<br>**path**: path where the volume is mounted.|
| usual.event.data.VOLUME_BAD_REMOVAL | **id**: ID of the volume.<br>**diskId**: ID of the disk to which the volume belongs.|
| usual.event.data.VOLUME_EJECT | **id**: ID of the volume.<br>**diskId**: ID of the disk to which the volume belongs.<br>**volumeState**: state of the volume.|
## How to Develop
Subscribe to broadcast events to notify the insertion and removal of external storage devices. The volumes can be queried and managed based on the volume information obtained from the broadcast.
1. Apply for permissions.
Apply for the **ohos.permission.STORAGE_MANAGER** permission for subscribing to volume broadcast events. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
2. Subscribe to broadcast events.
Subscribe to the following events:
- "usual.event.data.VOLUME_REMOVED": The device is removed.
- "usual.event.data.VOLUME_UNMOUNTED": The volume is unmounted.
- "usual.event.data.VOLUME_MOUNTED": The volume is mounted.
- "usual.event.data.VOLUME_BAD_REMOVAL": The device is forcibly removed.
- "usual.event.data.VOLUME_EJECT": The device is being ejected.
```ts
import CommonEvent from '@ohos.commonEventManager';
import volumeManager from '@ohos.file.volumeManager';
const subscribeInfo = {
events: [
"usual.event.data.VOLUME_REMOVED",
"usual.event.data.VOLUME_UNMOUNTED",
"usual.event.data.VOLUME_MOUNTED",
"usual.event.data.VOLUME_BAD_REMOVAL",
"usual.event.data.VOLUME_EJECT"
]
};
let subscriber = await CommonEvent.createSubscriber(subscribeInfo);
```
3. Obtain the volume information from the broadcast.
```ts
CommonEvent.subscribe(subscriber, function (err, data) {
if (data.event === 'usual.event.data.VOLUME_MOUNTED') {
// Manage the volume device based on the information obtained from the broadcast.
let volId = data.parameters.id;
volumeManager.getVolumeById(volId, function(error, vol) {
if (error) {
console.error('volumeManager getVolumeById failed');
} else {
console.info('volumeManager getVolumeById successfully, the volume state is ' + vol.state);
}
})
}
})
```
# Album Management
You can use the APIs provided by the **mediaLibrary** module to create and delete an album and obtain images in the album.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To ensure the application running efficiency, most **MediaLibrary** API calls are asynchronous, and both callback and promise modes are provided for these APIs. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## Obtaining Images and Videos in an Album
You can obtain images and videos in an album in either of the following ways:
- Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified to obtain the media assets. For details, see [Querying Media Assets with the Specified Album Name](medialibrary-resource-guidelines.md#querying-media-assets-with-the-specified-album-name).
- Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it. For details, see [Obtaining Images and Videos in an Album](medialibrary-resource-guidelines.md#obtaining-images-and-videos-in-an-album).
## Creating an Album
You can use [MediaLibrary.createAsset](../reference/apis/js-apis-medialibrary.md#createasset8-1), with the relative path set, to create an album while adding a media asset to the album. The relative path is the album name.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to create an album named **myAlbum**.
**How to Develop**
1. Call **getPublicDirectory** to obtain the public directory that stores files of a certain type.
For details about the operation, see [Obtaining a Public Directory](medialibrary-filepath-guidelines.md#obtaining-a-public-directory).
2. Call **createAsset** to create an image, with the relative path set to **path + 'myAlbum/'**.
This operation creates an album and adds an image to it.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.IMAGE;
let DIR_IMAGE = mediaLibrary.DirectoryType.DIR_IMAGE;
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_IMAGE);
// myAlbum is the path for storing the new file and the name of the new album.
media.createAsset(mediaType, 'test.jpg', path + 'myAlbum/', (err, fileAsset) => {
if (fileAsset === undefined) {
console.error('createAlbum failed, message = ' + err);
} else {
console.info('createAlbum successfully, message = ' + JSON.stringify(fileAsset));
}
});
}
```
## Renaming an Album
Renaming modifies the **FileAsset.albumName** attribute of the album, that is, the album name. After the modification, call [Album.commitModify](../reference/apis/js-apis-medialibrary.md#commitmodify8-3) to commit the modification to the database.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to rename the album **newAlbum**.
**How to Develop**
1. Create a retrieval condition for obtaining the target album.
2. Call **getAlbums** to obtain the album list.
3. Rename the album **newAlbum**.
4. Call **Album.commitModify** to commit the modification of the attributes to the database.
```ts
async function example() {
let AlbumNoArgsfetchOp = {
selections: '',
selectionArgs: [],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let albumList = await media.getAlbums(AlbumNoArgsfetchOp);
let album = albumList[0];
album.albumName = 'newAlbum';
// Void callback.
album.commitModify().then(() => {
console.info("albumRename successfully");
}).catch((err) => {
console.error("albumRename failed with error: " + err);
});
}
```
# File Path Management
User data on OpenHarmony is managed by the **mediaLibrary** module in a unified manner. You can use the APIs provided by this module to access and operate the user data.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To ensure the application running efficiency, most **MediaLibrary** API calls are asynchronous, and both callback and promise modes are provided for these APIs. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## File Formats Supported by Public Directories
Before using file paths for development, learn the file formats supported by each public directory.
> **CAUTION**
>
> The following table lists only the file types that can be identified by the system. In your application development, pay attention to the file formats supported by the corresponding interfaces. <br> For example, only .jpeg and .webp can be used for image encoding, and only .jpg, .png, .gif, .bmp, .webp, and .raw can be used for image decoding.
| Directory | Directory Type | Media Type | Description | Supported File Format |
| ---------- | ------------- | ------------- | -------------- | ------------------------------------------------------------ |
| Camera/ | DIR_CAMERA | VIDEO and IMAGE | Directory for storing images and videos taken by the camera. Videos and images can be stored in this directory and its subdirectories.| .bmp / .bm / .gif / .jpg /. jpeg / .jpe / .png / .webp / .raw / .svg / .heif / .mp4 / .3gp / .mpg / .mov / .webm / .mkv |
| Videos/ | DIR_VIDEO | VIDEO | Dedicated video directory. Only videos can be stored in this directory and its subdirectories.| .mp4 / .3gp / .mpg / .mov / .webm / .mkv |
| Pictures/ | DIR_IMAGE | IMAGE | Dedicated image directory. Only images can be stored in this directory and its subdirectories.| .bmp / .bm / .gif / .jpg /. jpeg / .jpe / .png / .webp / .raw / .svg / .heif |
| Audios/ | DIR_AUDIO | AUDIO |Dedicated audio directory. Only audio files can be stored in this directory and its subdirectories.| .aac/.mp3/.flac/.wav/.ogg |
| Documents/ | DIR_DOCUMENTS | FILE |Dedicated file directory. Only files except audios, images, and videos can be stored in this directory and its subdirectories.| - |
| Download/ | DIR_DOWNLOAD | ALLTYPE |Directory for storing downloaded files. The types of files in this directory and its subdirectories are not restricted.| - |
## Obtaining a Public Directory
Different types of files are stored in different public directories. You can call [getPublicDirectory](../reference/apis/js-apis-medialibrary.md#getpublicdirectory8-1) to obtain the public directory that stores files of a certain type.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
The following describes how to obtain the public directory that stores camera files.
```ts
async function example(){
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let DIR_CAMERA = mediaLibrary.DirectoryType.DIR_CAMERA;
const dicResult = await media.getPublicDirectory(DIR_CAMERA);
if (dicResult == 'Camera/') {
console.info('mediaLibraryTest : getPublicDirectory passed');
} else {
console.error('mediaLibraryTest : getPublicDirectory failed');
}
}
```
## Copying Files Between the Application Sandbox and the Public Directory
OpenHarmony provides the application sandbox to minimize the leakage of application data and user privacy information.
Users can access files stored in the public directories through the system applications **Files** and **Gallery**. However, files in the application sandbox can be accessed only by the application itself.
### Copying a File
You can call [mediaLibrary.FileAsset.open](../reference/apis/js-apis-medialibrary.md#open8-1) to open a file in a public directory.
You can call [fs.open](../reference/apis/js-apis-file-fs.md#fsopen) to open a file in the application sandbox. The sandbox directory can be accessed only through the application context.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permissions **ohos.permission.READ_MEDIA** and **ohos.permission.WRITE_MEDIA**.
- You have imported the module [@ohos.file.fs](../reference/apis/js-apis-file-fs.md) in addition to @ohos.multimedia.mediaLibrary.
- The **testFile.txt** file has been created and contains content.
**How to Develop**
1. Call [context.filesDir](../reference/apis/js-apis-file-fs.md) to obtain the directory of the application sandbox.
2. Call **MediaLibrary.getFileAssets** and **FetchFileResult.getFirstObject** to obtain the first file in the result set of the public directory.
3. Call **fs.open** to open the file in the sandbox.
4. Call **fileAsset.open** to open the file in the public directory.
5. Call [fs.copyfile](../reference/apis/js-apis-file-fs.md#fscopyfile) to copy the file.
6. Call **fileAsset.close** and [fs.close](../reference/apis/js-apis-file-fs.md#fsclose) to close the file.
**Example 1: Copying Files from the Public Directory to the Sandbox**
```ts
async function copyPublic2Sandbox() {
try {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let sandboxDirPath = context.filesDir;
let fileKeyObj = mediaLibrary.FileKey;
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?',
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
let fdPub = await fileAsset.open('rw');
let fdSand = await fs.open(sandboxDirPath + '/testFile.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.copyFile(fdPub, fdSand.fd);
await fileAsset.close(fdPub);
await fs.close(fdSand.fd);
let content_sand = await fs.readText(sandboxDirPath + '/testFile.txt');
console.info('content read from sandbox file: ', content_sand)
} catch (err) {
console.info('[demo] copyPublic2Sandbox fail, err: ', err);
}
}
```
**Example 2: Copying a File from the Sandbox to the Public Directory**
```ts
async function copySandbox2Public() {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let sandboxDirPath = context.filesDir;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const publicDirPath = await media.getPublicDirectory(DIR_DOCUMENTS);
try {
let fileAsset = await media.createAsset(mediaLibrary.MediaType.FILE, 'testFile02.txt', publicDirPath);
console.info('createFile successfully, message = ' + fileAsset);
} catch (err) {
console.error('createFile failed, message = ' + err);
}
try {
let fileKeyObj = mediaLibrary.FileKey;
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?',
selectionArgs: ['testFile02.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
var fileAsset = await fetchResult.getFirstObject();
} catch (err) {
console.error('file asset get failed, message = ' + err);
}
let fdPub = await fileAsset.open('rw');
let fdSand = await fs.open(sandboxDirPath + 'testFile.txt', fs.OpenMode.READ_WRITE);
await fs.copyFile(fdSand.fd, fdPub);
await fileAsset.close(fdPub);
await fs.close(fdSand.fd);
let fdPubRead = await fileAsset.open('rw');
try {
let arrayBuffer = new ArrayBuffer(4096);
await fs.read(fdPubRead, arrayBuffer);
var content_pub = String.fromCharCode(...new Uint8Array(arrayBuffer));
fileAsset.close(fdPubRead);
} catch (err) {
console.error('read text failed, message = ', err);
}
console.info('content read from public file: ', content_pub);
}
```
### Reading and Writing a File
You can use **FileAsset.open** and **FileAsset.close** of [mediaLibrary](../reference/apis/js-apis-medialibrary.md) to open and close a file, and use **fs.read** and **fs.write** in [file.fs](../reference/apis/js-apis-file-fs.md) to read and write the file.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permissions **ohos.permission.READ_MEDIA** and **ohos.permission.WRITE_MEDIA**.
- You have imported the module [@ohos.file.fs](../reference/apis/js-apis-file-fs.md) in addition to @ohos.multimedia.mediaLibrary.
**How to Develop**
1. Create a file.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.FILE;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_DOCUMENTS);
media.createAsset(mediaType, "testFile.txt", path).then((asset) => {
console.info("createAsset successfully:" + JSON.stringify(asset));
}).catch((err) => {
console.error("createAsset failed with error: " + err);
});
}
```
2. Call **FileAsset.open** to open the file.
3. Call [fs.write](../reference/apis/js-apis-file-fs.md#fswrite) to write a string to the file.
4. Call [fs.read](../reference/apis/js-apis-file-fs.md#fsread) to read the file and save the data read in an array buffer.
5. Convert the array buffer to a string.
6. Use **FileAsset.close** to close the file.
**Example 1: Opening an Existing File and Writing Data to It**
```ts
async function writeOnlyPromise() {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?',
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
console.info('fileAssetName: ', fileAsset.displayName);
try {
let fd = await fileAsset.open('w');
console.info('file descriptor: ', fd);
await fs.write(fd, "Write file test content.");
await fileAsset.close(fd);
} catch (err) {
console.error('write file failed, message = ', err);
}
}
```
**Example 2: Opening an Existing File and Reading Data from It**
```ts
async function readOnlyPromise() {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?' ,
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
console.info('fileAssetName: ', fileAsset.displayName);
try {
let fd = await fileAsset.open('r');
let arrayBuffer = new ArrayBuffer(4096);
await fs.read(fd, arrayBuffer);
let fileContent = String.fromCharCode(...new Uint8Array(arrayBuffer));
globalThis.fileContent = fileContent;
globalThis.fileName = fileAsset.displayName;
console.info('file content: ', fileContent);
await fileAsset.close(fd);
} catch (err) {
console.error('read file failed, message = ', err);
}
}
```
# MediaLibrary Development Overview
The **mediaLibrary** module provides APIs for you to access and modify media files.
- You can manage [media assets (audios, videos, image, and files)](medialibrary-resource-guidelines.md) as follows:
- Query media assets.
- Obtain an image or a video.
- Obtain the thumbnail of an image or a video.
- Create a media asset.
- Rename a media asset.
- Move a media asset to the recycle bin.
- You can manage [file paths](medialibrary-filepath-guidelines.md) as follows:
- Obtain the public directory that stores files of a certain type.
- Copy files between the application sandbox and the public directory.
- Read and write a file.
- You can manage [albums](medialibrary-album-guidelines.md) as follows:
- Obtain images and videos in an album.
- Create an album.
- Rename an album.
> **NOTE**
>
> This development guide applies only to the stage model (available from API version 9).
To access and modify personal media data, an application must obtain a **MediaLibrary** instance and request the media asset read and write permissions from the user. Unless otherwise specified, the **MediaLibrary** APIs are used in **pages/index.ets** or custom .ets files of the project code.
Before using the **MediaLibrary** APIs to develop features, you must learn how to:
- [Obtain a MediaLibrary Instance](#obtaining-a-medialibrary-instance)
- [Request Permissions](#requesting-permissions)
## Obtaining a MediaLibrary Instance
An application must call [getMediaLibrary](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary8) to obtain a **MediaLibrary** instance based on the application context. Through this instance, the application can access and modify personal media data (such as audios, videos, images, and files).
**How to Develop**
1. Import the **mediaLibrary** module.
2. Call **getContext** to obtain the application context.
3. Obtain a **MediaLibrary** instance.
```ts
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
```
## Requesting Permissions
To read and write a **MediaLibrary** instance, you must have the required permissions, as described in the table below. Before requesting the permissions, ensure that the [basic principles for permission management](../security/accesstoken-overview.md#basic-principles-for-permission-management) are met.
| Permission | Description | Authorization Mode |
| ------------------------------ | ------------------------------------------ | ---------- |
| ohos.permission.READ_MEDIA | Allows an application to read media files from the user's external storage.| user_grant |
| ohos.permission.WRITE_MEDIA | Allows an application to read media files from and write media files into the user's external storage.| user_grant |
| ohos.permission.MEDIA_LOCATION | Allows an application to access geographical locations in the user's media file.| user_grant |
After configuring the permissions in the **module.json5** file, the application must call [abilityAccessCtrl.requestPermissionsFromUser](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9) to check for the required permissions and if they are not granted, request the permissions from the user by displaying a dialog box.
> **NOTE**<br>Even if the user has granted a permission, the application must check for the permission before calling an API protected by the permission. It should not persist the permission granted status, because the user can revoke the permission through the system application **Settings**.
**How to Develop**
1. Declare the permissions in the **module.json5** file. Add the **requestPermissions** tag under **module** in the file, and set the tag based on the project requirements. For details about the tag, see [Guide for Requesting Permissions from User](../security/accesstoken-guidelines.md).
```json
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.MEDIA_LOCATION",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.READ_MEDIA",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.WRITE_MEDIA",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
}
]
}
}
```
2. In the **Ability.ts** file, call **requestPermissionsFromUser** in the **onWindowStageCreate** callback to check for the required permissions and if they are not granted, request the permissions from the user by displaying a dialog box.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import abilityAccessCtrl, {Permissions} from '@ohos.abilityAccessCtrl';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage) {
let list : Array<Permissions> = ['ohos.permission.READ_MEDIA', 'ohos.permission.WRITE_MEDIA'];
let permissionRequestResult;
let atManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(this.context, list, (err, result) => {
if (err) {
console.error('requestPermissionsFromUserError: ' + JSON.stringify(err));
} else {
permissionRequestResult = result;
console.info('permissionRequestResult: ' + JSON.stringify(permissionRequestResult));
}
});
}
}
```
# Media Asset Management
Your applications can use the APIs provided by the **mediaLibrary** module to perform operations on media assets such as audios, videos, images, and files.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To maximize the application running efficiency, most **MediaLibrary** API calls are asynchronous in callback or promise mode. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## Querying Media Assets
You can query media assets by condition such as the media type, date, or album name.
To do so, call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1), with a **MediaFetchOptions** object passed in to specify the conditions. In this object, **MediaFetchOptions.selections** are the retrieval conditions, and the enumerated values of **FileKey** are used as the column names of the conditions; **MediaFetchOptions.selectionArgs** are the values of the conditions. You can also specify **order** (sorting mode of the search result), **uri** (file URI), and **networkId** (network ID of the registered device) as the conditions.
To obtain the object at the specified position (for example, the first, the last, or with the specified index) in the result set, call [FetchFileResult](../reference/apis/js-apis-medialibrary.md#fetchfileresult7). In this section, **getNextObject** is used cyclically to obtain all media assets in the result set.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
### Querying Media Assets with the Specified Media Type
The following describes how to obtain images.
**How to Develop**
To specify the media type as the retrieval condition, set **selections** to **FileKey.MEDIA_TYPE**.
To specify the image as the media type, set **selectionArgs** to **MediaType.IMAGE**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let fileType = mediaLibrary.MediaType.IMAGE;
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
fetchFileResult.getFirstObject().then(async (fileAsset) => {
console.log('getFirstObject.displayName : ' + fileAsset.displayName);
for (let i = 1; i < fetchFileResult.getCount(); i++) {
let fileAsset = await fetchFileResult.getNextObject();
console.info('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
}
}).catch((err) => {
console.error('Failed to get first object: ' + err);
});
}
```
### Querying Media Assets with the Specified Date
The following describes how to obtain all the media assets that are added from the specified date. You can also use the modification date and shooting date as the retrieval conditions.
To specify the date when the files are added as the retrieval condition, set **selections** to **FileKey.DATE_ADDED**.
To specify the date 2022-8-5, set **selectionArgs** to **2022-8-5**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let option = {
selections: fileKeyObj.DATE_ADDED + '> ?',
selectionArgs: ['2022-8-5'],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
fetchFileResult.getFirstObject().then(async (fileAsset) => {
console.info('getFirstObject.displayName : ' + fileAsset.displayName);
for (let i = 1; i < fetchFileResult.getCount(); i++) {
let fileAsset = await fetchFileResult.getNextObject();
console.info('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
}
}).catch((err) => {
console.error('Failed to get first object: ' + err);
});
}
```
### Querying Media Assets and Sorting Them
The following describes how to query images and sort them in descending order by the date when they are added. You can also sort them in ascending order.
To sort files in descending order by the date when they are added, set **order** to **FileKey.DATE_ADDED + " DESC"**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let fileType = mediaLibrary.MediaType.IMAGE;
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
order: fileKeyObj.DATE_ADDED + " DESC",
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
fetchFileResult.getFirstObject().then(async (fileAsset) => {
console.info('getFirstObject.displayName : ' + fileAsset.displayName);
for (let i = 1; i < fetchFileResult.getCount(); i++) {
let fileAsset = await fetchFileResult.getNextObject();
console.info('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
}
}).catch((err) => {
console.error('Failed to get first object: ' + err);
});
}
```
### Querying Media Assets with the Specified Album Name
The following describes how to query media assets in **myAlbum**.
To specify the album name as the retrieval condition, set **selections** to **FileKey.ALBUM_NAME**.
To specify the album name **'myAlbum'**, set **selectionArgs** to **'myAlbum'**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let option = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs: ['myAlbum'],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
if (albumList.length > 0) {
fetchFileResult.getFirstObject().then((album) => {
console.info('getFirstObject.displayName : ' + album.albumName);
}).catch((err) => {
console.error('Failed to get first object: ' + err);
});
} else {
console.info('getAlbum list is: 0');
}
}
```
## Obtaining Images and Videos in an Album
You can obtain media assets in an album in either of the following ways:
- Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified, as described in [Querying Media Assets with the Specified Album Name](#querying-media-assets-with-the-specified-album-name).
- Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
**How to Develop**
The following describes how to obtain videos in an album named **New Album 1**.
1. Create a retrieval condition for obtaining the target **Album** instance.
```ts
let fileKeyObj = mediaLibrary.FileKey;
let AlbumNoArgsFetchOp = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs:['New Album 1']
}
```
2. Create a retrieval condition for obtaining videos in the target album.
```ts
let fileKeyObj = mediaLibrary.FileKey;
let videoType = mediaLibrary.MediaType.VIDEO;
let videoFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [videoType.toString()],
}
```
3. Call **Album.getFileAssets** to obtain the videos in the target album.
Complete sample code:
```ts
async function getCameraImagePromise() {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let videoType = mediaLibrary.MediaType.VIDEO;
let videoFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [videoType.toString()],
}
let AlbumNoArgsFetchOp = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs:['New Album 1']
}
let albumList = await media.getAlbums(AlbumNoArgsFetchOp);
if (albumList.length > 0) {
const album = albumList[0];
let fetchFileResult = await album.getFileAssets(videoFetchOp);
let count = fetchFileResult.getCount();
console.info("get mediaLibrary VIDEO number", count);
} else {
console.info('getAlbum list is: 0');
}
}
```
## Obtaining the Thumbnail of an Image or a Video
You can call [FileAsset.getThumbnail](../reference/apis/js-apis-medialibrary.md#getthumbnail8-2) with the thumbnail size passed in to obtain the thumbnail of an image or a video. Your application can use thumbnails to offer a quick preview on images and videos.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
### Obtaining the Thumbnail of an Image
The following describes how to obtain the thumbnail (size: 720 x 720) of the first image in the album.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Call **getThumbnail** to obtain the thumbnail of the first image.
```ts
async function getFirstThumbnailPromise() {
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.IMAGE;
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [imageType.toString()],
}
let size = { width: 720, height: 720 };
const fetchFileResult = await media.getFileAssets(imagesFetchOp);
if (fetchFileResult === undefined) {
console.error("get image failed with error");
return;
} else {
const asset = await fetchFileResult.getFirstObject();
asset.getThumbnail(size).then((pixelMap) => {
pixelMap.getImageInfo().then((info) => {
console.info('get Thumbnail info: ' + "width: " + info.size.width + " height: " + info.size.height);
}).catch((err) => {
console.error("getImageInfo failed with error: " + err);
});
}).catch((err) => {
console.error("getImageInfo failed with error: " + err);
});
}
}
```
## Creating a Media Asset
You can call [MediaLibrary.createAsset](../reference/apis/js-apis-medialibrary.md#createasset8-1) to create a media asset.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
- [You have obtained a public directory](medialibrary-filepath-guidelines.md).
The following describes how to create a file of the **MediaType.FILE** type.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.FILE;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_DOCUMENTS);
media.createAsset(mediaType, "testFile.text", path).then((asset) => {
console.info("createAsset successfully:"+ JSON.stringify(asset));
}).catch((err) => {
console.error("createAsset failed with error: " + err);
});
}
```
## Moving a Media Asset to the Recycle Bin
You can use [FileAsset.trash](../reference/apis/js-apis-medialibrary.md#trash8) to move a media asset to the recycle bin.
By default, files in the recycle bin will be stored for 30 days before being permanently removed. During this period, you can set **isTrash** in **trash** to **false** to recover the files. Application users can also recover the files through the system applications **Files** or **Gallery**.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to move the first file in the result set to the recycle bin.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Call **trash** to move the first image to the recycle bin.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let fileType = mediaLibrary.MediaType.FILE;
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
let asset = await fetchFileResult.getFirstObject();
if (asset === undefined) {
console.error('asset not exist');
return;
}
// Void callback.
asset.trash(true).then(() => {
console.info("trash successfully");
}).catch((err) => {
console.error("trash failed with error: " + err);
});
}
```
## Renaming a Media Asset
To rename a media asset, modify the **FileAsset.displayName** attribute (which specifies the displayed file name, including the file name extension) and commit the modification through [FileAsset.commitModify](../reference/apis/js-apis-medialibrary.md#commitmodify8-1).
Before renaming a file, you must obtain the file, for example, by calling [FetchFileResult](../reference/apis/js-apis-medialibrary.md#fetchfileresult7).
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to rename the first file in the result set as **newImage.jpg**.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Rename the image as **newImage.jpg**.
5. Call **FileAsset.commitModify** to commit the modification to the database.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey;
let fileType = mediaLibrary.MediaType.IMAGE;
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
let media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
let asset = await fetchFileResult.getFirstObject();
if (asset === undefined) {
console.error('asset not exist');
return;
}
asset.displayName = 'newImage.jpg';
// Void callback.
asset.commitModify((err) => {
if (err) {
console.error('fileRename Failed ');
return;
}
console.info('fileRename successful.');
});
}
```
# Saving User Files
When a user needs to download a file from the network to a local directory or save a user file into another directory, use **FilePicker** to save the file.
The operations for saving images, audio or video clips, and documents are similar. Call **save()** of the corresponding picker instance and pass in **saveOptions**.
## Saving Images or Video Files
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create a **photoSaveOptions** instance.
```ts
const photoSaveOptions = new picker.PhotoSaveOptions(); // Create a photoSaveOptions instance.
photoSaveOptions.newFileNames = ["PhotoViewPicker01.jpg"]; // (Optional) Set the names of the files to save.
```
3. Create a **photoViewPicker** instance and call [save()](../reference/apis/js-apis-file-picker.md#save) to open the **FilePicker** page to save the files.
After the user selects the target folder, the file saving operation is complete. After the files are saved successfully, the URIs of the files saved are returned.
```ts
const photoViewPicker = new picker.PhotoViewPicker();
photoViewPicker.save(photoSaveOptions)
.then(async (photoSaveResult) => {
let uri = photoSaveResult[0];
// Perform operations on the files based on the file URIs obtained.
})
.catch((err) => {
console.error(`Invoke documentPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
## Saving Documents
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create a **documentSaveOptions** instance.
```ts
const documentSaveOptions = new picker.DocumentSaveOptions(); // Create a documentSaveOptions instance.
documentSaveOptions.newFileNames = ["DocumentViewPicker01.txt"]; // (Optional) Set the names of the documents to save.
```
3. Create a **documentViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-3) to open the **FilePicker** page to save the documents.
After the user selects the target folder, the file saving operation is complete. After the files are saved successfully, the URIs of the files saved are returned.
> **NOTE**
>
> Currently, **DocumentSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
const documentViewPicker = new picker.DocumentViewPicker(); // Create a documentViewPicker instance.
documentViewPicker.save(documentSaveOptions)
.then(async (documentSaveResult) => {
let uri = documentSaveResult[0];
// For example, write data to the documents based on the obtained URIs.
})
.catch((err) => {
console.error(`Invoke documentPicker.save failed, code is ${err.code}, message is ${err.message}`);
})
```
## Saving Audio Files
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create an **audioSaveOptions** instance.
```ts
const audioSaveOptions = new picker.AudioSaveOptions(); // Create an audioSaveOptions instance.
audioSaveOptions.newFileNames = ['AudioViewPicker01.mp3']; // (Optional) Set the names of the files to save.
```
3. Create an **audioViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-6) to open the **FilePicker** page to save the files.
After the user selects the target folder, the file saving operation is complete. After the files are saved successfully, the URIs of the files saved are returned.
> **NOTE**
>
> Currently, **AudioSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.save(audioSaveOptions)
.then((audioSelectResult) => {
let uri = audioSelectResult[0];
// Perform operations on the audio files based on the file URIs.
})
.catch((err) => {
console.error(`Invoke audioPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
# Selecting User Files
If your application needs to support share and saving of user files (such as images and videos) by users, you can use the [FilePicker](../reference/apis/js-apis-file-picker.md) prebuilt in OpenHarmony to implement selecting and saving of user files.
The **FilePicker** provides the following interfaces by file type:
- [**PhotoViewPicker**](../reference/apis/js-apis-file-picker.md#photoviewpicker): used to select and save images or video files.
- [**DocumentViewPicker**](../reference/apis/js-apis-file-picker.md#documentviewpicker): used to select and save documents.
- [**AudioViewPicker**](../reference/apis/js-apis-file-picker.md#audioviewpicker): used to select and save audio files.
## Selecting Images or Video Files
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create a **photoSelectOptions** instance.
```ts
const photoSelectOptions = new picker.PhotoSelectOptions();
```
3. Set the file type and the maximum number of media files to select.
For example, select a maximum of five images. For details about the media file type, see [PhotoViewMIMETypes](../reference/apis/js-apis-file-picker.md#photoviewmimetypes).
```ts
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // Select images.
photoSelectOptions.maxSelectNumber = 5; // Set the maximum number of images to select.
```
4. Create a **photoPicker** instance and call [select()](../reference/apis/js-apis-file-picker.md#select) to open the **FilePicker** page for the user to select files.
Use [PhotoSelectResult](../reference/apis/js-apis-file-picker.md#photoselectresult) to return a result set. Further operations on the selected files can be performed based on the file URIs in the result set.
```ts
const photoPicker = new picker.PhotoViewPicker();
photoPicker.select(photoSelectOptions)
.then(async (photoSelectResult) => {
let uri = photoSelectResult.photoUris[0];
// Perform operations on the files based on the file URIs obtained.
})
.catch((err) => {
console.error(`Invoke documentPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
## Selecting Documents
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create a **documentSelectOptions** instance.
```ts
const documentSelectOptions = new picker.DocumentSelectOptions();
```
3. Create a **documentViewPicker** instance, and call [**select()**](../reference/apis/js-apis-file-picker.md#select-3) to open the **FilePicker** page for the user to select documents.
After the documents are selected successfully, a result set containing the file URIs is returned. Further operations can be performed on the documents based on the file URIs.
> **NOTE**
>
> Currently, **DocumentSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
const documentViewPicker = new picker.DocumentViewPicker(); // Create a documentViewPicker instance.
documentViewPicker.select(documentSelectOptions)
.then((documentSelectResult) => {
let uri = documentSelectResult[0];
// Perform operations on the documents based on the file URIs.
})
.catch((err) => {
console.error(`Invoke documentPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
## Selecting an Audio File
1. Import the **FilePicker** module.
```ts
import picker from '@ohos.file.picker';
```
2. Create an **audioSelectOptions** instance.
```ts
const audioSelectOptions = new picker.AudioSelectOptions();
```
3. Create an **audioViewPicker** instance, and call [**select()**](../reference/apis/js-apis-file-picker.md#select-6) to open the **FilePicker** page for the user to select audio files.
After the files are selected successfully, a result set containing the URIs of the audio files selected is returned. Further operations can be performed on the documents based on the file URIs.
For example, use the [file management interface](../reference/apis/js-apis-file-fs.md) to obtain the file handle (FD) of the audio clip based on the URI, and then develop the audio playback function based on the media service. For details, see [Audio Playback Development](../media/audio-playback-overview.md).
> **NOTE**
>
> Currently, **AudioSelectOptions** is not configurable. By default, all types of user files are selected.
```ts
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.select(audioSelectOptions)
.then(audioSelectResult => {
let uri = audioSelectOptions[0];
// Perform operations on the audio files based on the file URIs.
})
.catch((err) => {
console.error(`Invoke audioPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
```
# Sending Files to an Application Sandbox
During the development and debugging process of an application, you may need to place some files to the application sandbox for intra-application access or for testing purposes. In this case, you can use either of the following methods:
1. Use DevEco Studio to place the files to the application installation directory. For details, see [Application Installation Resource Access](../quick-start/resource-categories-and-access.md# resource-access).
2. Use the hdc tool to send files to the application sandbox directory on the device. This section describes the second method.
However, the file directories visible to the debugged process in the hdc shell are different from the application sandbox directories visible to the application. You need to understand the mappings between the application sandbox directories and the physical (real) directories.
## Mappings Between Application Sandbox Directories and Physical Directories
The read and write operations performed based on the application sandbox paths via APIs are performed on the files in the physical directories after address conversion. The following table lists the mappings between application sandbox paths and physical paths.
**Table 1** Mapping between application sandbox paths and physical paths
| Application Sandbox Path| Physical Path in hdc| Description|
| -------- | -------- | -------- |
| /data/storage/el1/bundle | /data/app/el1/bundle/public/&lt;PACKAGENAME&gt; | Application installation package directory.|
| /data/storage/el1/base | /data/app/el1/&lt;USERID&gt;/base/&lt;PACKAGENAME&gt; | Application directory of encryption level (el) 1.|
| /data/storage/el2/base | /data/app/el2/&lt;USERID&gt;/base/&lt;PACKAGENAME&gt; | Application directory of el 2.|
| /data/storage/el1/database | /data/app/el1/&lt;USERID&gt;/database/&lt;PACKAGENAME&gt; | Database directory of the application under **el1/**.|
| /data/storage/el2/database | /data/app/el2/&lt;USERID&gt;/database/&lt;PACKAGENAME&gt; | Database directory of the application under **el2/**.|
| /data/storage/el2/distributedfiles | /mnt/hmdfs/&lt;USERID&gt;/account/merge_view/data/&lt;PACKAGENAME&gt; | Distributed data directory of the application under **el2/**.|
## Development Example
The following uses the application bundle **com.ohos.example** as an example. If the application sandbox path is **/data/storage/el1/bundle**, the physical path is **/data/app/el1/bundle/public/<PACKAGENAME>**, that is, **/data/app/el1/bundle/public/com.ohos.example**.
Run the following command to send the file:
```
hdc file send ${Path of the local file to send} /data/app/el1/bundle/public/com.ohos.example/
```
## Switching to the Application View
During the debugging process, if you do not have the permission or the file does not exist, you need to switch from the process view to the application view and further analyze permission and directory problems. To switch to the application view, run the following commands:
```
hdc shell // Switch to shell.
ps -ef|grep [hapName] // Obtain the process identifier (PID) of the application.
nsenter -t [hapPid] -m /bin/sh // Enter the application sandbox environment based on the PID.
```
The application view is in use, and the path you see is the application sandbox path.
# Setting the Security Level of a Distributed File
The security capabilities vary with devices. For example, small embedded devices provide fewer security capabilities than tablets. The security requirements also vary with data. For example, personal health information and bank card information are not expected to be accessed by devices of lower security levels. OpenHarmony provides a complete set of standards for data and device classification and custom data transfer policies for different devices. For details, see [Data and Device Security Classification](../database/access-control-by-device-and-data-level.md).
## Available APIs
For details about the APIs, see [ohos.file.securityLabel](../reference/apis/js-apis-file-securityLabel.md).
**Table 1** APIs
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| -------- | -------- | -------- | -------- | -------- |
| setSecurityLabel | Sets a security label for a file.| Method| √ | √ |
| getSecurityLabel | Obtains the security label of a file.| Method| √ | √ |
> **NOTICE**
>
> 1. In distributed networking, a device can view the files that do not match its security level but cannot access them.
>
> 2. The default security level of the distributed file system data is S3. Applications can set the security level of files.
## Development Example
Obtain the sandbox path of the file and set the data security label. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
```ts
import securityLabel from '@ohos.file.securityLabel';
//Obtain the sandbox path of the file.
let context =...; // Obtain UIAbilityContext information.
let pathDir = context.filesDir;
let filePath = pathDir + '/test.txt';
// Set the data level of the file to S0.
securityLabel.setSecurityLabel(filePath, 's0').then(() => {
console.info('Succeeded in setSecurityLabeling.');
}).catch((err) => {
console.error(`Failed to setSecurityLabel. Code: ${err.code}, message: ${err.message}`);
});
```
<!--no_check-->
\ No newline at end of file
# Sharing an Application File
The file of an application can be shared with another application based on the file descriptor (FD) or uniform resource identifier (URI) of the file. However, if the FD of a shared file is closed, the file cannot be opened. Therefore, the file sharing based on the FD is not recommended. This section describes how to share an application file based on its URI.
- You can use **wantConstant.Flags()** of the [ohos.app.ability.wantConstant](../reference/apis/js-apis-app-ability-wantConstant.md#wantconstantflags) module to share an application file in read or read/write mode based on its URI with another application. The target application can use **open()** of the [ohos.file.fs](../reference/apis/js-apis-file-fs.md#fsopen) module to open the URI and then perform read and/or write operations based on the permissions granted. Currently, OpenHarmony API version 9 supports only temporary authorization. The permission on shared file is revoked once the target application exits.
- You can also use **open()** of the ohos.file.fs module to share an application file with the specified permissions to another application based on the FD. After parsing the FD from **Want**, the target application can read and write the file by using **read()** and **write()** APIs of ohos.file.fs.
You can use the related APIs to [share a file with another application](#sharing-a-file-with-another-application) or [use shared application files](#using-shared-files).
## File URI Specifications
The file URIs are in the following format:
file://&lt;bundleName&gt;/&lt;path&gt;/\#networkid=&lt;networkid&gt;
- **file**: indicates a file URI.
- *bundleName*: specifies the owner of the file.
- *path*: specifies the application sandbox path of the file.
- *networkid* (optional): specifies the device to which the file belongs in a distributed file system. Leave this parameter unspecified if the file location does not need to be set.
## Sharing a File with Another Application
Before sharing application files, you need to [obtain the application file path](../application-models/application-context-stage.md#obtaining-the-application-development-path).
1. Obtain the application sandbox path of the file and convert it into the file URI.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import fileuri from '@ohos.file.fileuri';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
// Obtain the application sandbox path of the file.
let pathInSandbox = this.context.filesDir + "/test.txt";
// Convert the application sandbox path into a URI.
let uri = fileuri.getUriFromPath(pathInSandbox);
// The obtained URI is file://com.example.demo/data/storage/el2/base/files/test.txt.
}
}
```
2. Set the target application, with which you want to share the file, and grant permissions on the file.
Use [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to share the file with the target application. You need to pass in the URI obtained in **uri** of the **want** parameter, set the type of the file to share, set **action** to **ohos.want.action.sendData**, and set the granted permission on the file in **flags**. For details, see [Want](../reference/apis/js-apis-app-ability-want.md#attributes).
> **NOTE**
>
> The write permission granted includes the read permission.
```ts
import fileuri from '@ohos.file.fileuri';
import window from '@ohos.window';
import wantConstant from '@ohos.app.ability.wantConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
// Obtain the application sandbox path of the file.
let filePath = this.context.filesDir + '/test.txt';
// Convert the application sandbox path into a URI.
let uri = fileuri.getUriFromPath(filePath);
let want = {
// Grant the read and write permissions on the shared file to the target application.
flags: wantConstant.Flags.FLAG_AUTH_WRITE_URI_PERMISSION | wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION,
// Set the implicit startup rule for the application that shares the file.
action: 'ohos.want.action.sendData',
uri: uri,
type: 'text/plain'
}
this.context.startAbility(want)
.then(() => {
console.info('Invoke getCurrentBundleStats succeeded.');
})
.catch((err) => {
console.error(`Invoke startAbility failed, code is ${err.code}, message is ${err.message}`);
});
}
...
}
```
## Using Shared Files
In the [**module.json5** file](../quick-start/module-configuration-file.md) of the application, which wants to use the shared file, set **actions** to **ohos.want.action.sendData** to allow the application to receive files shared by another application and set **uris** to the type of the URI to receive. In the following example, the application receives only .txt files with **scheme** of **file**.
```json
{
"module": {
...
"abilities": [
{
...
"skills": [
{
...
"actions": [
"ohos.want.action.sendData"
],
"uris": [
{
"scheme": "file",
"type": "text/plain"
}
]
}
]
}
]
}
}
```
After **UIAbility** of the application starts, the application obtains **want** information from [**onCreate()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) or [**onNewWant()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonnewwant).
After obtaining the URI of the shared file through **want**, the application can call **fs.open()** to open the file, and then read and write the file after obtaining the related file object.
```ts
// xxx.ets
import fs from '@ohos.file.fs';
function getShareFile() {
try {
let want =...; // Obtain the want information sent from the application that shares the file.
// Obtain the uri field from the want information.
let uri = want.uri;
if (uri == null || uri == undefined) {
console.info('uri is invalid');
return;
}
try {
// Perform operations on the URI of the shared file as required. For example, open the URI to obtain the file object in read/write mode.
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
console.info('open file successfully!');
} catch (error) {
console.error(`Invoke openSync failed, code is ${error.code}, message is ${error.message}`);
}
} catch (error) {
console.error(`Invoke openSync failed, code is ${error.code}, message is ${error.message}`);
}
}
```
# User File Overview
User files are the private images, video and audio clips, and documents of the user who logs in to the device.
1. User files are stored in a directory, whose owner is the user who logs in to the device.
2. User files can be stored in [built-in storage](#built-in-storage) and [external storage](#external-storage).
3. An application cannot access user files without user authorization, or the operations on user files must be performed by the user.
OpenHarmony provides the [user file access framework](#user-file-access-framework) for developers to access and manage user files, which will be described in detail below.
## User File Storage
### Built-in Storage
Built-in storage refers to the internal storage device (space) of a device. The built-in storage device cannot be removed. The following files can be stored in the built-in storage of a device:
- Files owned by a user: The files belong to the user who logs in to the device. Different users who log in to a device can view only their own files.
These user files can be classified into the following types based on file attributes and access habits of users/applications:
- Image/Video files
The files have attributes, such as the shooting time, location, rotation angle, and file width and height information, and are stored in media file formats. The files are usually presented as media files or albums, without the specific location in the system.
- Audio files
The files have attributes, such as the album, creator, and shooting duration information, and are stored in media file formats. Generally, the files are presented by file, album, or creator, without the specific location in the system.
- Documents
The files are stored as common files, including common text files, compressed files, and images, videos and audio clips stored as common files. These files are presented in a directory tree.
- Files shared by users: The files are stored in a directory for share and shared by multiple users.
The files in the shared directory are stored as common files and presented in a directory tree.
### External Storage
External storage is not inside a device's main storage or memory. Common external storage devices include pluggable devices, such as SD cards and USB flash drives. Same as the files in the shared directory of the built-in storage device, the files in an external storage device can be viewed by all the users who log in to the system.
External storage devices are pluggable. OpenHarmony provides the functions of listening for the device insertion and removal events and mounting/unmounting an external storage device. For details, see [Managing External Storage Devices)](manage-external-storage.md).
The files on external storage devices are presented as common files in a directory tree, like the documents stored in built-in storage.
## User File Access Framework
OpenHarmony provides the user file access framework for developers to access and manage user files. This framework leverages the ExtensionAbility of OpenHarmony to provide a set of methods and interfaces for accessing user files.
**Figure 1** User file access framework
![User file access framework](figures/user-file-access-framework.png)
- To access user files, for example, select a photo or save multiple documents, a system application or third-party application (file access client in **Figure 1**) starts the **FilePicker** application.
- OpenHarmony is prebuilt with the **FilePicker** and **FileManager** applications.
- **FilePicker**: provides APIs for a file access client to select and save user files without any permission. For details, see [Selecting User Files](select-user-file.md).
- **FileManager**: allows users to view and modify files, and delete, rename, move, and create files or directories by using a system FileManager.
You can also develop your own FilePicker or FileManager applications as required. FilePicker is a subset of FileManager. For details about how to develop a FileManager application, see [Developing a FileManager Application)](dev-user-file-manager.md).
- The user file access framework provides the following functional modules:
- **File Access Helper**: provides APIs for the **FileManager** and **FilePicker** to access user files.
- **File Access ExtensionAbility**: provides a file access framework to implement file access functions. The **File Access ExtensionAbility** consists of the following:
- **UserFileManager**: implements management of the files stored on the built-in storage.
- **ExternalFileManager**: implements management of the files stored on the external storage.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册