HarmonyOS鸿蒙Next中如何把文件管理的文件放到沙箱里面

HarmonyOS鸿蒙Next中如何把文件管理的文件放到沙箱里面 我做了一个功能就是打开了文件管理,选择音频文件把他放到沙箱里面,然后再使用的时候可以临时调用他,应该怎么办

5 回复

开发者您好,你可以通过文件选择器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


您这个类似与用户选择文件进行预览,您可以参考官方说明

如何实现通过文件选择器(FilePicker)选择文件进行预览

使用这个Core File Kit (@kit.CoreFileKit) 提供的文件复制功能

在HarmonyOS Next中,文件管理的文件默认存储在应用沙箱内。应用通过context.filesDir等接口访问私有目录。若需将设备公共存储的文件移入沙箱,可使用FileManagermovecopy接口,指定源路径(如external://...)和目标沙箱路径。注意,操作可能需申请ohos.permission.READ_MEDIAohos.permission.WRITE_MEDIA权限。

在HarmonyOS Next中,将文件管理器中选中的文件(如音频)放入应用沙箱,核心是使用Picker选择文件后,通过FileManageropenFile接口获取其内容,再写入到应用沙箱路径下。以下是关键步骤和代码示例:

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获取,该目录为应用私有,其他应用无法直接访问。
  • 文件操作:使用FileManageropenFile接口可以安全地访问通过Picker获取的用户文件URI,再通过fileIo进行读写。
  • 临时使用:沙箱内的文件在应用卸载时会自动清除,适合作为临时缓存。如需持久化,应考虑使用用户公共目录(如媒体库)并申请相应权限。

此方案实现了从文件管理器选择音频文件,安全复制到应用沙箱,并进行后续使用的完整流程。

回到顶部