# HarmonyOS NEXT Practical: Sandbox Tool

Objective: Encapsulate the sandbox tool to save files to the sandbox and clear sandbox files.

Knowledge points: Before using this function module to operate on files/directories, it is necessary to first obtain the application sandbox path, retrieval method, and interface:getContext().cacheDir

fs: Before using this function module to operate on files/directories, it is necessary to first obtain their application sandbox path. The string representing the sandbox path is called 'path'. Please refer to 'Application Context - Get Application File Path' for the retrieval method and interface usage. The string pointing to a resource is called a URI. For interfaces that only support path as an input parameter, the URI can be converted to path by constructing a fileUri object and obtaining its path property, and then using the file interface.

[fs.open](http://fs.open)： Open the file and use Promise asynchronous callback. \[code\] open(path: string, mode?: number): Promise \[/code\] path： The application sandbox path or file URI of the file. mode： The option to open a file must specify one of the following options, which will be opened in read-only mode by default:

* OpenMode. READ\_ONLY(0o0)： Read only open.
    
* OpenMode. WRITE\_ONLY(0o1)： Only write open.
    
* OpenMode. READ\_WRITE(0o2)： Read and write open. Given the following functional options, append them in a bitwise or manner, and no additional options are given by default:
    
* OpenMode. CREATE(0o100)： If the file does not exist, create the file.
    
* OpenMode. TRUNC(0o1000)： If the file exists and has write permission, crop its length to zero.
    
* OpenMode. APPEND(0o2000)： Open in append mode, and subsequent writes will be appended to the end of the file.
    
* OpenMode. NONBLOCK(0o4000)： If the path points to a FIFO, block special file, or character special file, then this open and subsequent IO operations will be non blocking.
    
* OpenMode. DIR(0o200000)： If the path does not point to a directory, an error occurs. Do not allow additional write permissions.
    
* OpenMode. NOFOLLOW(0o400000)： If the path points to a symbolic link, an error occurs.
    
* OpenMode. SYNC(0o4010000)： Open files in synchronous IO mode.
    

fs.access： Check if the current process can access a file and use Promise asynchronous callback. fs.mkdirSync： Create a directory using synchronous methods. fs.copyFile： Copy the file and use Promise asynchronous callback. fs.close： Close the file and use Promise asynchronous callback. fs.rmdir： Delete the entire directory and use Promise to return asynchronously. fs.listFileSync： List all file names in the folder synchronously. Support recursive listing of all file names (including subdirectories) and file filtering.

Actual combat: SandboxUtil

```plaintext
import fs from '@ohos.file.fs';
import { util } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 沙箱工具类
 */
class SandboxUtil {
  private sandboxDir:string ='/sandbox'

  /**
   * 保存文件到沙箱
   * @param src
   * @returns 沙箱地址
   */
  async saveToSandbox(src: string): Promise<string> {
    let sandboxUri: string = ''
    for (let index = 0; index < src.length; index++) {
      const uri = src;
      try {
        const originalFile = await fs.open(uri)
        const targetFileDirPath = getContext().cacheDir + this.sandboxDir
        const fileName = util.generateRandomUUID() + uri.split("/").pop() ?? ''
        if (!fs.accessSync(targetFileDirPath)) {
          fs.mkdirSync(targetFileDirPath, true)
        }
        const targetFile =
          await fs.open(`${targetFileDirPath}/${fileName}`,
            fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
        await fs.copyFile(originalFile.fd, targetFile.fd)
        await fs.close(originalFile.fd);
        await fs.close(targetFile.fd);
        sandboxUri=targetFile.path
      } catch (e) {
        const err = e as BusinessError
        console.error(`[log]MediaPicker saveToSandbox, err=${JSON.stringify(err)}`); //err.code == 13900001 文件失效
      }
    }
    return sandboxUri
  }

  /**
   * 清除沙箱文件
   */
  clear() {
    const targetFileDirPath = getContext().cacheDir + this.sandboxDir
    fs.rmdir(targetFileDirPath);
  }

  /**
   * 获取沙箱路径下所有文件名，支持递归列出所有文件名（包含子目录下），并以日志形式打印
   * 用于检查沙箱情况
   */
  print() {
    const targetFileDir = getContext().cacheDir + this.sandboxDir
    if (fs.accessSync(targetFileDir)) {
      let listFile = fs.listFileSync(targetFileDir, { recursion: true })
      let listFileStr = listFile.join('\n');
      console.log(`[log]postVideoSandbox print, listFileStr=${JSON.stringify(listFileStr)}`);
    } else {
      console.log(`[log]postVideoSandbox print, 目标文件不存在, targetFileDir=${JSON.stringify(targetFileDir)}`);
    }
  }
}

const sandboxUtil = new SandboxUtil()

export default sandboxUtil
```

use

```plaintext
import sandboxUtil from './SandboxUtil';

@Entry
@Component
struct SandboxDemoPage {
  @State message: string = 'SandboxDemo';

  build() {
    Column() {
      Text(this.message)
        .fontSize($r('app.float.page_text_font_size'))
        .fontWeight(FontWeight.Bold)
      Button('保存文件')
        .onClick(()=>{
          sandboxUtil.saveToSandbox('fielPath')
        })
      Button('删除文件')
        .onClick(()=>{
          sandboxUtil.clear()
        })
    }
    .height('100%')
    .width('100%')
  }
}
```
