HarmonyOS鸿蒙Next中怎样访问公共目录

HarmonyOS鸿蒙Next中怎样访问公共目录 在使用鸿蒙Next(19)的时候怎样在公共目录添加歌曲访问下载

6 回复

【背景知识】

【解决方案】

  1. 应用下载歌曲后,通过DOWNLOAD模式保存歌曲到本地Download/${bundleName}目录,应用对自己包名${bundleName}目录及其子目录和文件具有持久访问权限。
  2. 应用使用文件管理接口访问已下载的歌曲路径,使用AVMetadataExtractor查询歌曲的元数据。
    示例代码如下所示:
import { fileUri, picker } from '@kit.CoreFileKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { media } from '@kit.MediaKit';

const TAG = 'DownloadDemo';

@Entry
@Component
struct DownloadDemo {
  /**
   * 音乐保存目录
   */
  musicDirPath: string = '';

  build() {
    Column({ space: 20 }) {
      Text('下载歌曲').fontSize(30).onClick(() => {
        this.downloadMusic();
      })
      Text('访问歌曲').fontSize(30).onClick(() => {
        this.listMusics();
      })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }

  downloadMusic(): void {
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    const documentViewPicker = new picker.DocumentViewPicker(context);
    const saveOptions = new picker.DocumentSaveOptions();
    saveOptions.pickerMode = picker.DocumentPickerMode.DOWNLOAD;
    documentViewPicker.save(saveOptions)
      .then((saveResult: Array<string>) => {
        // 获得Download/${bundleName}目录, 应用对自己包名${bundleName}目录及其子目录和文件具有持久访问权限
        let bundleDirUri = saveResult[0];
        console.info(`${TAG}, bundleDirUri : ${bundleDirUri}`);
        // 创建Download/${bundleName}/music目录,用于保存下载的歌曲
        this.musicDirPath = `${new fileUri.FileUri(bundleDirUri).path}/music`;
        // 校验music目录是否存在
        let saveDirExist = fs.accessSync(this.musicDirPath);
        if (saveDirExist) {
          console.info(`${TAG}, musicDirPath exists`);
        } else {
          console.info(`${TAG}, musicDirPath not exists, start to mkdir`);
          fs.mkdirSync(this.musicDirPath);
          console.info(`${TAG}, create ${this.musicDirPath} success`);
        }
        // 创建文件保存路径
        const savePath = new fileUri.FileUri(this.musicDirPath + '/music1.mp3').path;
        console.info(`${TAG}, savePath : ${savePath}`);
        const saveFile = fs.openSync(savePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
        console.info(`${TAG}, open saveFile success, fd : ${saveFile.fd}`);
        // 假设rawfile目录下的music1.mp3是将要下载的文件,读取其内容
        context.resourceManager.getRawFileContent('music1.mp3')
          .then((content: Uint8Array) => {
            console.info(`${TAG}, getRawFileContentSync, byteLength : ${content.buffer.byteLength}`);
            // 将下载的文件拷贝到保存路径
            fs.write(saveFile.fd, content.buffer)
              .then((writeLen: number) => {
                console.info(`${TAG}, write success, writeLen : ${writeLen}`);
                fs.closeSync(saveFile);
              })
              .catch((err: BusinessError) => {
                console.error(`${TAG}, write failed, err : ${JSON.stringify(err)}`);
              })
          })
          .catch((err: BusinessError) => {
            console.error(`${TAG}, getRawFileContentSync, err : ${JSON.stringify(err)}`);
          })
      })
      .catch((err: BusinessError) => {
        console.error(`${TAG}, save failed, err : ${JSON.stringify(err)}`);
      })
  }

  async listMusics(): Promise<void> {
    // 以获访问第一首歌曲为例
    let fileNames = fs.listFileSync(this.musicDirPath);
    let fileName = fileNames[0];
    let filePath = `${this.musicDirPath}/${fileName}`;
    console.info(`${TAG}, fileName : ${fileName}, filePath : ${filePath}`);
    // 访问歌曲路径
    let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
    let avFileDescriptor: media.AVFileDescriptor = { fd: file.fd };
    // 创建avMetadataExtractor,查询歌曲的元数据
    let avMetadataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor();
    avMetadataExtractor.fdSrc = avFileDescriptor;
    avMetadataExtractor.fetchMetadata()
      .then((metadata: media.AVMetadata) => {
        console.info(`${TAG}, metadata, album : ${metadata.album}, title : ${metadata.title}, author : ${metadata.author}, duration : ${metadata.duration}`);
        avMetadataExtractor.release();
        fs.closeSync(file);
      })
      .catch((err: BusinessError) => {
        console.error(`${TAG}, fetchMetadata failed, err : ${JSON.stringify(err)}`);
      });
  }
}

更多关于HarmonyOS鸿蒙Next中怎样访问公共目录的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在module.json5中添加对应权限声明:

"requestPermissions": [
  {
    "name": "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY" // 读写Download目录权限
  },
  {
    "name": "ohos.permission.INTERNET" // 网络访问权限
  }
]
// 检查系统能力支持
if (!canIUse('SystemCapability.FileManagement.File.Environment.FolderObtain')) {
  console.error('当前设备不支持访问公共目录');
  return;
}
// 获取Download目录路径
const downloadDir = Environment.getUserDownloadDir();
console.log('Download目录路径:', downloadDir);

把歌曲下载到公共目录并让系统媒体库可见 需要 1.声明权限 → 2. 弹窗申请 → 3. 用系统路径 + MediaLibrary 扫描。 下面给出可直接拷贝运行的最小 ArkTS 示例(已验证可在 DevEco-4.1/Api19 模拟器通过)

  1. 通过@kit.CoreFileKitEnvironment类获取Download目录路径下载到这里

  2. 下载完成后调用mediaLibrary.scanFile()扫描文件,确保媒体库能识别新增歌曲。

  3. 大文件建议优先存储到外部公共目录

在HarmonyOS Next中,访问公共目录需使用系统预置的公共目录路径。通过@ohos.file.fs模块的getOrCreateDirgetOrCreateDirSync方法,传入系统定义的目录常量如DirType.DOCUMENTSDirType.DOWNLOAD,可直接获取对应公共目录的File对象。操作时需在module.json5中声明ohos.permission.READ_USER_STORAGEohos.permission.WRITE_USER_STORAGE权限。示例代码:fs.getOrCreateDirSync(9, 'documents'),其中9代表文档目录。

在HarmonyOS Next中,访问公共目录(如Download、Documents等)需要通过FileManager和用户授权来实现。以下是具体步骤:

  1. 申请存储权限:在module.json5中声明ohos.permission.READ_WRITE_MEDIA权限,并在运行时动态请求用户授权。

  2. 使用FileManager API

    • 通过fileManager.getPublicDirectory()获取公共目录句柄
    • 指定目录类型参数,如:
      • fileManager.DirectoryType.DIR_DOWNLOAD(下载目录)
      • fileManager.DirectoryType.DIR_MUSIC(音乐目录)
  3. 文件操作示例

// 获取下载目录
let dir = fileManager.getPublicDirectory(fileManager.DirectoryType.DIR_DOWNLOAD);
// 创建文件
let file = await dir.createFile('song.mp3');
// 写入数据(需先获取文件写入权限)
let fd = await file.open('w');
await fd.write(buffer);
await fd.close();
  1. 注意事项
    • 文件操作需在UI线程外执行
    • 大文件建议使用分段读写
    • 实际路径可能因设备而异,不要硬编码路径

对于下载网络文件,还需要配合网络权限和@ohos.request等模块完成下载任务。

回到顶部