HarmonyOS鸿蒙Next中文件如何存储的公共目录
HarmonyOS鸿蒙Next中文件如何存储的公共目录
【背景知识】
HarmonyOS为应用提供了两种将文件存储到公共目录的方案,解决不同场景应用及用户对文件的使用诉求,同时保障了文件使用的安全性与隐私性。
-
方案一:下载控件效果介绍。应用存在下载场景时,用户希望将文件下载到指定的本地公共目录。下载控件帮应用在下载目录创建文件夹并完成目录级授权(如:我的手机->下载->XXX),应用可将文件下载到此目录(应用具备此目录读写权限)。目录所有权归用户,应用和用户均可见。
- 方式一:提供系统标准下载icon控件(控件仅提供样式,点击事件需要适配DocumentViewPicker.saveAPI)
- 方式二:三方自定义的下载界面(点击事件调用DocumentViewPicker.saveAPI)。
-
方案二:FilePicker效果介绍:单次保存,每次弹框,目录可选,精准保存
下载控件 | FilePicker | |
---|---|---|
权限差异 | 1、对“下载>xx应用”目录具有长期读写权限 2、本应用仅可访问本应用下载目录(权限限制到应用,防止其他应用恶意删除本应用下载文件) |
对用户选择另存为的文件具有长期读写权限(无目录权限,只可读写保存的文件) |
保存路径 | 无法自定义,固定为“下载>xx应用”(目录固定,培养用户习惯,大量下载时便于用户根据应用查找) | 用户可选择本地任意目录(目录灵活,适合单次下载精准保存) |
处理文件数量 | 目录权限给应用后,由应用决定,支持一次下载多个文件(大量下载时方便使用) | 一次弹框只能保存一个文件(大量下载时,频繁操作,使用繁琐) |
弹框差异 | 无需弹框 (下载体验一步直达) | 另存为文件时每次需要弹出FilePicker窗口 (每次弹框,操作繁琐) |
重命名或删除目录 | URI变化权限清除,需要重新调用下载控件创建目录 | URI变化权限清除,需重新调用picker授权 |
卸载后文件处理 | 应用卸载后,下载目录不会删除 (保证用户文件不丢失) | 应用卸载后,另存为文件不会删除 (保证用户文件不丢失) |
【解决方案】
推荐应用接入下载控件,参考demo如下:
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
import { BusinessError } from '@ohos.base';
import common from '@ohos.app.ability.common';
import FileUri from '@ohos.file.fileuri';
import { DownloadDescription, DownloadFileButton, DownloadIconStyle,
DownloadLayoutDirection } from '@ohos.arkui.advanced.DownloadFileButton';
const documentSaveOptions = new picker.DocumentSaveOptions();
documentSaveOptions.pickerMode = picker.DocumentPickerMode.DOWNLOAD;
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State text: string = '';
controller: TextInputController = new TextInputController();
private constUri: string = '';
build() {
Row() {
Column() {
Text('方式一: 使用ICON控件')
.fontSize(20)
.border({ width: 1 })
.borderRadius(10)
.lineHeight(28)
.margin(30)
Row() {
Text('输入文件名: ')
.fontSize(20)
.border({ width: 1 })
.borderRadius(10)
.lineHeight(28)
.margin(10)
TextInput({ text: this.text, placeholder: 'examples.doc', controller: this.controller })
.placeholderColor(Color.Grey)
.placeholderFont({ size: 20, weight: 150 })
.caretColor(Color.Blue)
.width('50%')
.height(40)
.margin(30)
.fontSize(16).fontColor(Color.Black)
.onChange((value: string) => {
this.text = value
})
}
// 标准下载icon控件
DownloadFileButton({
contentOptions: { // 指定元素内容下载按钮
icon: DownloadIconStyle.FULL_FILLED,
text: DownloadDescription.DOWNLOAD
},
styleOptions: { // 指定元素样式的下载按钮
iconSize: '20vp',
layoutDirection: DownloadLayoutDirection.VERTICAL,
fontSize: '16vp',
fontStyle: FontStyle.Normal,
fontWeight: FontWeight.Medium,
fontFamily: 'HarmonyOS Sans',
fontColor: '#ffffffff',
iconColor: '#ffffffff',
textIconSpace: '4vp'
}
})
// .backgroundColor('#007dff')
.onClick(() => {
this.downloadAction();
})
Text('方式二: 使用DocumentViewPicker')
.fontSize(20)
.border({ width: 1 })
.borderRadius(10)
.lineHeight(28)
.margin(30)
Row() {
Text('输入文件名: ')
.fontSize(20)
.border({ width: 1 })
.borderRadius(10)
.lineHeight(28)
.margin(10)
TextInput({ text: this.text, placeholder: 'examples.doc', controller: this.controller })
.placeholderColor(Color.Grey)
.placeholderFont({ size: 20, weight: 150 })
.caretColor(Color.Blue)
.width('50%')
.height(40)
.margin(30)
.fontSize(16)
.fontColor(Color.Black)
.onChange((value: string) => {
this.text = value
})
}
// 三方自定义/框架的下载界面
Button("下载")
.onClick(() => {
this.downloadAction();
})
}
.width('100%')
}
.height('100%')
.backgroundColor($r('sys.color.ohos_id_color_sub_background'))
}
downloadAction() {
let filePath = new FileUri.FileUri(this.constUri).path;
filePath = filePath.replace('/data/storage/el2/share/rw/docs', '');
console.error(`this.constUri: ` + this.constUri + filePath);
// 判断应用专属目录是否存在
if (!fs.accessSync(filePath)) {
// 不存在拉起弹窗,创建应用专属目录,返回uri
this.creatFolderAndGrant();
} else {
// 存在则将文件保存在该URI下
this.writeFileInFolder(this.constUri);
}
}
creatFolderAndGrant() {
let context = getContext(this) as common.Context;
const documentViewPicker = new picker.DocumentViewPicker(context);
// 创建文件管理器选项实例
const documentSaveOptions = new picker.DocumentSaveOptions();
// 配置保存的模式为DOWNLOAD
documentSaveOptions.pickerMode = picker.DocumentPickerMode.DOWNLOAD;
// save接口拉起弹窗,点击同意,返回应用专属目录uri
documentViewPicker.save(documentSaveOptions ).then((documentSaveResult: Array<string>) => {
console.error(`documentViewPicker ` + documentSaveResult[0]);
let uri = documentSaveResult[0];
// 保存应用专属目录uri,后续用户可以直接将文件保存在该URI下
this.constUri = uri;
}).catch((err: BusinessError) => {
console.error(`Invoke documentViewPicker.save failed, code is ${err.code}, message is ${err.message}`);
})
}
async writeFileInFolder(uri: string) {
try {
let path: string = new FileUri.FileUri(uri).path
let filePath: string = `${path}/${this.text}`;
// 测试权限并创建
const testCreateFile = await fs.open(filePath, fs.OpenMode.CREATE)
.catch((err: string) => console.error(`Invoke documentViewPicker.save failed`));
if (testCreateFile) {
fs.closeSync(testCreateFile.fd);
}
let fileContent = 'Hello, world!';
let createRes: fs.File | BusinessError = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
fs.writeSync(createRes.fd, fileContent);
fs.closeSync(createRes);
} catch (err) {
console.error(`create file failed, code is ${err.code}, message is ${err.message}`);
}
}
}
更多关于HarmonyOS鸿蒙Next中文件如何存储的公共目录的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS Next的文件存储采用应用沙箱机制,公共目录通过特定URI访问。用户文件存储在媒体库,包括图片、视频、音频和文档目录,通过PhotoViewPicker等选择器获取访问权限。下载文件存放于Download目录。应用数据存储在沙箱内,外部访问需授权。文件管理遵循分类存储原则,不同类型文件对应不同目录路径,确保数据隔离与安全。
在HarmonyOS Next中,文件存储的公共目录主要通过应用沙箱和公共数据访问权限实现。系统为每个应用分配独立的沙箱目录(如/data/storage/el1/bundle
),用于私有数据存储。若需访问公共目录(如相册、下载文件夹),需通过FileManager
API并申请相应权限(如ohos.permission.READ_IMAGEVIDEO
)。例如,使用getPublicDirectory()
方法可获取公共路径,但需注意权限管理和用户授权流程。具体实现可参考官方文档的FileManager
模块说明。