HarmonyOS鸿蒙Next中如何把文件管理的文件放到沙箱里面
HarmonyOS鸿蒙Next中如何把文件管理的文件放到沙箱里面 我做了一个功能就是打开了文件管理,选择音频文件把他放到沙箱里面,然后再使用的时候可以临时调用他,应该怎么办
开发者您好,你可以通过文件选择器picker选择相应音频文件,通过fs.copyFileSync方法存入沙箱目录;可通过avplayer方式调用沙箱音频文件进行播放,可通过fs.read方法读取音频文件的二进制数据。
以下为示例demo,音频文件为MP3文件:
// Index.ets
import common from '@ohos.app.ability.common';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo as fs, picker } from '@kit.CoreFileKit';
import media from '@ohos.multimedia.media';
async function readAudioData(sandboxPath: string) {
try {
const file = fs.openSync(sandboxPath, fs.OpenMode.READ_ONLY);
const stat = await fs.stat(sandboxPath);
const buffer = new ArrayBuffer(stat.size);
await fs.read(file.fd, buffer); // 读取文件内容
fs.closeSync(file);
console.info('buffer.size = ' + buffer.byteLength); // 二进制文件大小
} catch (err) {
console.error(`读取失败:${JSON.stringify(err)}`);
}
}
@Entry
@Component
struct Index {
context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
filePath: string = '';
private avPlayer?: media.AVPlayer;
// 创建播放器并设置回调
async initPlayer(url: string) {
// 创建实例
this.avPlayer = await media.createAVPlayer();
// 注册状态监听
this.avPlayer.on('stateChange', (state: string) => {
switch (state) {
case 'initialized': // 资源设置完成
this.avPlayer!.prepare();
break;
case 'prepared': // 准备就绪
this.avPlayer!.play();
console.info('开始播放');
break;
case 'completed': // 播放结束
this.avPlayer!.stop();
this.release()
break;
}
});
this.avPlayer.url = `fd://${fs.openSync(url).fd}`; // 传入沙箱地址
console.info('url = ' + this.avPlayer.url);
}
// 播放控制
play() {
if (this.avPlayer?.state === 'paused') {
this.avPlayer.play();
}
}
pause() {
if (this.avPlayer?.state === 'playing') {
this.avPlayer.pause();
}
}
// 销毁资源
release() {
this.avPlayer?.release();
}
// 拉起Picker选择1个音频MP3文件并复制文件到沙箱
docPickerSelectThenCopy2Sandbox() {
try {
// 1. 拉起Picker选择1个文件
let documentSelectOptions = new picker.DocumentSelectOptions();
documentSelectOptions.maxSelectNumber = 1; // 选择文件最大个数1
let documentPicker = new picker.DocumentViewPicker(this.context);
documentPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
console.info('DocumentViewPicker.select successfully, documentSelectResult uri: ' +
JSON.stringify(documentSelectResult));
let pickerUri = documentSelectResult[0];
// 2. 复制文件到沙箱
let file = fs.openSync(pickerUri, fs.OpenMode.READ_ONLY);
let pathDir = this.context.filesDir;
this.filePath = pathDir + '/' + file.name; // 沙箱文件路径
console.info('filePath = ' + this.filePath);
fs.copyFileSync(file.fd, this.filePath);
fs.closeSync(file);
console.info('copy success');
}).catch((err: BusinessError) => {
console.error(`DocumentViewPicker.select failed with err, code is: ${err.code}, message is: ${err.message}`);
});
} catch (error) {
let err: BusinessError = error as BusinessError;
console.error(`DocumentViewPicker failed with err, code is: ${err.code}, message is: ${err.message}`);
}
}
build() {
Column() {
// 保存MP3音频文件到沙箱
Button('保存音频文件到沙箱')
.fontSize(30)
.onClick(() => {
this.docPickerSelectThenCopy2Sandbox();
});
// 播放沙箱MP3音频文件
Button('播放音频').onClick(() => {
this.initPlayer(this.filePath);
});
Button('暂停').onClick(() => this.pause());
// 获取沙箱音频文件二进制数据
Button('获取沙箱音频文件二进制数据')
.fontSize(30)
.onClick(() => {
readAudioData(this.filePath);
});
}
.height('100%')
.width('100%');
}
}
另外需要在module.json5中声明沙箱文件访问权限:
"requestPermissions": [
{
"name": "ohos.permission.FILE_ACCESS_PERSIST",
"reason": "$string:reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
]
更多关于HarmonyOS鸿蒙Next中如何把文件管理的文件放到沙箱里面的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
您这个类似与用户选择文件进行预览,您可以参考官方说明
使用这个Core File Kit (@kit.CoreFileKit) 提供的文件复制功能
在HarmonyOS Next中,文件管理的文件默认存储在应用沙箱内。应用通过context.filesDir等接口访问私有目录。若需将设备公共存储的文件移入沙箱,可使用FileManager的move或copy接口,指定源路径(如external://...)和目标沙箱路径。注意,操作可能需申请ohos.permission.READ_MEDIA或ohos.permission.WRITE_MEDIA权限。
在HarmonyOS Next中,将文件管理器中选中的文件(如音频)放入应用沙箱,核心是使用Picker选择文件后,通过FileManager的openFile接口获取其内容,再写入到应用沙箱路径下。以下是关键步骤和代码示例:
1. 申请必要权限
在module.json5文件中声明文件访问权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.READ_MEDIA",
"reason": "$string:reason_desc" // 用于读取媒体文件
}
]
}
}
2. 使用文件选择器(Picker)选择文件
启动文件选择器,让用户选择目标音频文件:
import { picker } from '@kit.FileKit';
import { BusinessError } from '@kit.BasicServicesKit';
let audioUris: Array<string> = []; // 用于存储选中文件的URI
// 启动音频文件选择器
try {
let audioSelectOptions = new picker.AudioSelectOptions();
audioSelectOptions.MIMEType = picker.AudioType.AUDIO_TYPE_ALL; // 选择所有音频类型
audioSelectOptions.maxSelectNumber = 1; // 示例:选择1个文件
picker.select(audioSelectOptions).then((uris: Array<string>) => {
audioUris = uris;
if (audioUris.length > 0) {
console.info('Audio selected successfully, URI: ' + audioUris[0]);
// 调用函数将文件复制到沙箱
copyToSandbox(audioUris[0]);
}
}).catch((err: BusinessError) => {
console.error('Failed to select audio. Error: ' + JSON.stringify(err));
});
} catch (error) {
console.error('Failed to launch audio picker. Error: ' + JSON.stringify(error));
}
3. 将文件复制到应用沙箱
获取到文件URI后,使用FileManager打开并读取该文件,然后写入到应用沙箱目录:
import { fileIo } from '@kit.CoreFileKit';
import { fileManager } from '@kit.FileKit';
import { BusinessError } from '@kit.BasicServicesKit';
async function copyToSandbox(sourceUri: string): Promise<void> {
// 定义沙箱目标路径,例如在应用文件目录下创建"temp_audio"文件夹
let sandboxDir: string = getContext().filesDir + '/temp_audio/';
let fileName: string = sourceUri.split('/').pop() || 'audio_file'; // 提取原文件名
let destPath: string = sandboxDir + fileName;
try {
// 1. 确保沙箱目标目录存在
await ensureDirectoryExists(sandboxDir);
// 2. 通过FileManager打开源文件,获取其File对象
let file: fileManager.File = await fileManager.openFile({ uri: sourceUri });
let sourceFile: fileIo.File = await file.openFile('r'); // 以只读方式打开
// 3. 在沙箱路径创建并打开目标文件
let destFile: fileIo.File = await fileIo.open(destPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE);
// 4. 读取源文件内容并写入目标文件
let buffer: ArrayBuffer = new ArrayBuffer(1024 * 1024); // 1MB缓冲区
let readLen: number = 0;
while ((readLen = await sourceFile.read(buffer)) > 0) {
await destFile.write(buffer.slice(0, readLen));
}
// 5. 关闭文件流
await sourceFile.close();
await destFile.close();
await file.close();
console.info('File copied to sandbox successfully: ' + destPath);
} catch (error) {
console.error('Failed to copy file to sandbox. Error: ' + JSON.stringify(error));
}
}
// 辅助函数:确保目录存在
async function ensureDirectoryExists(dirPath: string): Promise<void> {
try {
await fileIo.access(dirPath);
} catch (error) {
// 目录不存在,则创建
await fileIo.mkdir(dirPath, true);
}
}
4. 临时调用沙箱内的文件
文件复制到沙箱后,你可以直接通过沙箱路径(如destPath)进行访问和操作。例如,使用媒体播放器播放该音频:
import { media } from '@kit.MediaKit';
// 使用沙箱内的音频文件路径创建播放器
let audioPlayer: media.AudioPlayer | undefined = undefined;
async function playSandboxAudio(filePath: string): Promise<void> {
try {
audioPlayer = await media.createAudioPlayer();
audioPlayer.src = filePath; // 直接使用沙箱文件路径
audioPlayer.play();
} catch (error) {
console.error('Failed to play audio. Error: ' + JSON.stringify(error));
}
}
关键点说明:
- 权限管理:读取用户文件需要声明
READ_MEDIA权限,并在运行时动态申请(如果需要)。 - 沙箱路径:应用沙箱内的文件路径通过
getContext().filesDir获取,该目录为应用私有,其他应用无法直接访问。 - 文件操作:使用
FileManager的openFile接口可以安全地访问通过Picker获取的用户文件URI,再通过fileIo进行读写。 - 临时使用:沙箱内的文件在应用卸载时会自动清除,适合作为临时缓存。如需持久化,应考虑使用用户公共目录(如
媒体库)并申请相应权限。
此方案实现了从文件管理器选择音频文件,安全复制到应用沙箱,并进行后续使用的完整流程。

