##HarmonyOS Next实战##HarmonyOS SDK应用服务##教育##
目标:封装沙箱工具,通过沙箱工具保存文件到沙箱中和清除沙箱文件。
知识点:
使用该功能模块对文件/目录进行操作前,需要先获取其应用沙箱路径,获取方式及其接口:getContext().cacheDir
fs:使用该功能模块对文件/目录进行操作前,需要先获取其应用沙箱路径。表示沙箱路径的字符串称为path,获取方式及其接口用法请参考:应用上下文Context-获取应用文件路径。
将指向资源的字符串称为URI。对于只支持path作为入参的接口可使用构造fileUri对象并获取其path属性的方式将URI转换为path,然后使用文件接口。
fs.open:打开文件,使用Promise异步回调。
open(path: string, mode?: number): Promise<File>
path:文件的应用沙箱路径或文件URI。
mode:打开文件的选项,必须指定如下选项中的一个,默认以只读方式打开:
- OpenMode.READ_ONLY(0o0):只读打开。
- OpenMode.WRITE_ONLY(0o1):只写打开。
- OpenMode.READ_WRITE(0o2):读写打开。
给定如下功能选项,以按位或的方式追加,默认不给定任何额外选项:
- OpenMode.CREATE(0o100):若文件不存在,则创建文件。
- OpenMode.TRUNC(0o1000):如果文件存在且文件具有写权限,则将其长度裁剪为零。
- OpenMode.APPEND(0o2000):以追加方式打开,后续写将追加到文件末尾。
- OpenMode.NONBLOCK(0o4000):如果path指向FIFO、块特殊文件或字符特殊文件,则本次打开及后续 IO 进行非阻塞操作。
- OpenMode.DIR(0o200000):如果path不指向目录,则出错。不允许附加写权限。
- OpenMode.NOFOLLOW(0o400000):如果path指向符号链接,则出错。
- OpenMode.SYNC(0o4010000):以同步IO的方式打开文件。
fs.access:检查当前进程是否可访问某文件,使用Promise异步回调。
fs.mkdirSync:以同步方法创建目录。
fs.copyFile:复制文件,使用Promise异步回调。
fs.close:关闭文件,使用Promise异步回调。
fs.rmdir:删除整个目录,使用Promise异步返回。
fs.listFileSync:以同步方式列出文件夹下所有文件名。支持递归列出所有文件名(包含子目录下),支持文件过滤。
实战:SandboxUtil
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
使用
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%')
}
}