HarmonyOS 鸿蒙Next中沙箱文件如何存媒体库?

HarmonyOS 鸿蒙Next中沙箱文件如何存媒体库? 沙箱文件如何存媒体库?

3 回复

效果展示

cke_1010.png

实现思路

cke_1979.png

完整代码

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError, request } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';

async function savePhotoToGallery(context: common.UIAbilityContext, url:string) {
  let helper = photoAccessHelper.getPhotoAccessHelper(context);
  try {
    // onClick触发后10秒内通过createAsset接口创建图片文件,10秒后createAsset权限收回。
    let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
    // 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
    let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
    // 写到媒体库文件中
    const source = image.createImageSource(url) // 图片对象
    const packer = image.createImagePacker() // 创建打包对象
    const buffer = await packer.packing(source, {
      quality: 100,
      format: 'image/jpeg'
    })
    await fileIo.write(file.fd, buffer);
    await fileIo.close(file.fd);
    promptAction.showToast({ message: '已保存至相册!' });
  }
  catch (error) {
    const err: BusinessError = error as BusinessError;
    console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
  }
}

@Entry
@Component
struct Index {
  build() {
    Row() {
      Column({ space: 10 }) {
        // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件
        Image('http://tmp00002.zhaodashen.cn/jd.png').width('100%')


        SaveButton()
          .padding({top: 12, bottom: 12, left: 24, right: 24})
          .onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
            if (result === SaveButtonOnClickResult.SUCCESS) {
              const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              // 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
              // =======================
              try {
                // 需要手动将 url 替换为真实服务器的 HTTP 协议地址
                request.downloadFile(
                  getContext(),
                  {
                    url: 'http://tmp00002.zhaodashen.cn/jd.png',
                    filePath: context.filesDir + '/hello3.jpg'
                  }
                ).then((data: request.DownloadTask) => {
                  let downloadTask: request.DownloadTask = data;

                  downloadTask.on('progress', (receivedSize: number, totalSize: number) => {
                    console.log('下载中:', receivedSize, totalSize)
                  })

                  downloadTask.on('complete', () => {
                    console.log('下载完成') // 保存到媒体库中✅
                    savePhotoToGallery(context, context.filesDir + '/hello3.jpg');
                  })
                }).catch((err: BusinessError) => {
                  console.error(`Failed to request the download. Code: ${err.code}, message: ${err.message}`);
                })
              } catch (err) {
                console.error(`Failed to request the download. err: ${JSON.stringify(err)}`);
              }
              // =======================
            } else {
              promptAction.showToast({ message: '设置权限失败!' })
            }
          })
      }
      .width('100%')
    }
    .height('100%')
    .backgroundColor(0xF1F3F5)
  }
}

更多关于HarmonyOS 鸿蒙Next中沙箱文件如何存媒体库?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,应用沙箱内的媒体文件通过媒体库接口进行管理。使用@ohos.file.photoAccessHelper@ohos.file.videoAccessHelper模块,调用createAsset()方法可将沙箱文件存入媒体库。需先申请ohos.permission.READ_IMAGEVIDEOohos.permission.WRITE_IMAGEVIDEO权限。文件存入后,系统会为其分配URI,可通过媒体库查询和管理。

在HarmonyOS Next中,将沙箱内的文件(如应用私有目录中的图片、视频)存入系统媒体库,需要使用媒体库管理模块 @ohos.file.mediaLibrary 提供的接口。核心思路是:将沙箱内的源文件复制或移动到媒体库管理的公共目录下,并调用媒体库的插入接口使其被系统扫描和收录

以下是关键步骤和代码示例:

1. 获取媒体库实例与公共目录访问权限

首先需要申请媒体库读写权限(ohos.permission.READ_MEDIAohos.permission.WRITE_MEDIA),并在代码中获取媒体库管理对象及公共目录。

import mediaLibrary from '@ohos.file.mediaLibrary';

// 获取媒体库单例对象
let media = mediaLibrary.getMediaLibrary(context);

// 获取公共目录路径,例如公共图片目录
let publicPath = await media.getPublicDirectory(mediaLibrary.DirectoryType.DIR_IMAGE);

2. 准备源文件与目标路径

假设你的应用沙箱内有一个图片文件 privateImage.jpg,位于应用文件目录 context.filesDir 下。

import fs from '@ohos.file.fs';

// 沙箱内源文件路径
let sourceFile = context.filesDir + '/privateImage.jpg';
// 在公共目录下创建目标文件路径
let destFile = publicPath + '/myAppImage.jpg';

3. 复制文件到公共目录

使用文件系统接口将文件从沙箱复制到媒体库公共目录。

try {
  // 复制文件(也可使用移动 moveFile)
  fs.copyFileSync(sourceFile, destFile);
  console.log('File copied to public directory.');
} catch (err) {
  console.error('Failed to copy file: ' + err.message);
}

4. 插入媒体库并刷新

复制完成后,需要调用媒体库的插入接口,通知系统将新文件扫描入库。

// 创建文件资源对象,指向目标文件
let fileAsset = await media.createAsset(
  mediaLibrary.MediaType.IMAGE, // 媒体类型,如图片、视频
  'myAppImage.jpg',             // 显示名称
  publicPath                    // 所在目录
);

if (fileAsset !== undefined) {
  console.log('File inserted into media library with ID: ' + fileAsset.id);
  // 可选:触发媒体库刷新(部分场景系统会自动扫描)
  // mediaLibrary.getMediaLibrary().on('mediaLibraryChange', (args) => {});
}

注意事项:

  • 权限申请:必须在 module.json5 中声明权限,并在运行时动态申请用户授权。
  • 文件类型:根据媒体类型(图片、视频、音频)选择对应的 DirectoryType(如 DIR_IMAGEDIR_VIDEO)。
  • 文件覆盖:若目标文件已存在,复制或插入可能会失败,需提前检查或处理命名冲突。
  • 资源释放:操作完成后,及时释放媒体库对象资源(如 media.release())。

通过以上步骤,即可将沙箱内的文件安全存入系统媒体库,供其他应用访问或系统相册显示。

回到顶部