写点什么

HarmonyOS 5.0 应用开发——用户文件操作

作者:高心星
  • 2024-11-01
    江苏
  • 本文字数:3198 字

    阅读完需:约 10 分钟

HarmonyOS 5.0应用开发——用户文件操作

【高心星出品】


用户文件操作

用户文件:文件所有者为登录到该终端设备的用户,包括用户私有的图片、视频、音频、文档等。


用户文件存放在用户目录下,归属于该设备上登录的用户。


用户文件存储位置主要分为内置存储、外置存储。


应用对用户文件的创建、访问、删除等行为,需要提前获取用户授权,或由用户操作完成。

文件 URI

用户文件 uri 是文件的唯一标识,在对用户文件进行访问与修改等操作时往往都会使用到 uri,不建议开发者解析 uri 中的片段用于业务代码开发,不同类型的 uri 使用方式将在下文详细介绍。

URI 类型

uri 类型可以归纳为文档类 uri 和媒体文件 uri 两类


  • 文档类 uri:由 picker 拉起文件管理器选择或保存返回,以及通过 fileAccess 模块获取。具体获取方式参见文档类 uri 获取方式。

  • 媒体文件 uri:由 picker 通过拉起图库选择图片或者视频返回,通过 photoAccessHelper 模块获取图片或者视频文件的 uri,以及通过 userFileManager 模块获取图片、视频或者音频文件的 uri。具体获取方式参见媒体文件 uri 获取方式。



用户文件的选取与保存

用户需要分享文件、保存图片、视频等用户文件时,开发者可以通过系统预置的文件选择器(FilePicker),实现该能力。通过 Picker 访问相关文件,将拉起对应的应用,引导用户完成界面操作,接口本身无需申请权限。picker 获取的 uri 只具有临时权限,获取持久化权限需要通过 FilePicker 设置永久授权方式获取。


根据用户文件的常见类型,选择器(FilePicker)分别提供以下选项:


  • PhotoViewPicker:适用于图片或视频类型文件的选择与保存(该接口在后续版本不再演进)。请使用 PhotoAccessHelper 的 PhotoViewPicker 来选择图片文件。请使用安全控件创建媒体资源。

  • DocumentViewPicker:适用于文件类型文件的选择与保存。DocumentViewPicker 对接的选择资源来自于 FilePicker, 负责文件类型的资源管理,文件类型不区分后缀,比如浏览器下载的图片、文档等,都属于文件类型。

  • AudioViewPicker:适用于音频类型文件的选择与保存。AudioViewPicker 目前对接的选择资源来自于 FilePicker。

图片或视频的选取与保存

选取


首先拉起相册图片选择器,然后选择图片,获取图片的 URI,进而读取该图片为字节数组,再转化为 Bitmap 来进行展示。


再读取过程中,考虑到内存优化问题,没有一次性将图片内容完全读入内存,而是分批读取,通过 buffer 模块拼接成字节数组。



// 选取图片    let picker = new photoAccessHelper.PhotoViewPicker()    // 配置选择图片的个数 支持编辑图片    let option: photoAccessHelper.PhotoSelectOptions = {      maxSelectNumber: 1,      isEditSupported: true    }    picker.select(option).then((result) => {      // 选取的图片uri file://media/Photo/......      let uri = result.photoUris[0]      // 打开该文件      let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)      // 创建缓冲区      let totalbuffer = buffer.alloc(fileIo.statSync(file.fd).size)      // 每次读出的字节个数      let buffersize = 2048      // 偏移量      let off = 0      // 每次读出的字节真实个数      let len = 0      let buffer1 = new ArrayBuffer(buffersize)      //  循环读字节      while (len = fileIo.readSync(file.fd, buffer1, { offset: off, length: buffersize })) {        //  填充到缓冲区        totalbuffer.fill(new Uint8Array(buffer1.slice(0, len)), off)        // 更新偏移量        off += len        // 如果剩余字节不足2048 那么就将剩余字节个数视为缓存长度        if (totalbuffer.length - off < buffersize) {          buffersize = totalbuffer.length - off        }      }      //  这里面都是字节数组转化成图片      let pm = image.createImageSource(totalbuffer.buffer).createPixelMapSync()      this.src = pm    })
复制代码


保存


如果要保存相册或者视频到用户文件系统中,就牵涉到了权限问题,需要申请权限,但是鸿蒙提供了临时权限授予组件 savebutton,可以直接使用授予临时权限,进行文件保存。


SaveButton({ text: SaveDescription.SAVE_IMAGE })  .width('60%')  .onClick(() => {    this.savepic()  })    //---------savepic的逻辑如下:  savepic() {    //   获取资源图片的缓存器    let buffer = this.context.resourceManager.getMediaContentSync($r('app.media.startIcon').id).buffer    //  创建图片保存器    let helper = photoAccessHelper.getPhotoAccessHelper(this.context)    // 图片保存请求    let request =      photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(this.context, photoAccessHelper.PhotoType.IMAGE,        'jpg')    //  加入相册    request.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, buffer)    // 将加入相册的请求执行    helper.applyChanges(request)  }
复制代码
文档的选取与保存

文档选取


首先拉起文档选择器,然后获取选择文档的 URI,然后读取该 URI 对应用户文件的字节,保存到数组,再写入到应用沙箱中。


这里面考虑到内存优化的问题,在读写过程中,使用了边读边写的方式。



// 文档选择器let docpicker = new picker.DocumentViewPicker()// 文档选择器配置 最多选择数量  默认打开目录  文件后缀let option: picker.DocumentSelectOptions = {  maxSelectNumber: 1,  defaultFilePathUri: 'file://docs/storage/Users/currentUser',  fileSuffixFilters: ['.doc', '.docx', '.txt', '.xlsx', '.mp3']}docpicker.select(option).then((result) => {  // 文档的uri  let uri = result[0]  // 获取文档的名字  let name = decodeURI(uri.slice(uri.lastIndexOf('/') + 1))  // 要写入的文件  let destfile =    fileIo.openSync(getContext(this).tempDir + '/' + name, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY)  // 要读的文件  let srcfile = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)  // 缓存大小  let buffersize = 2048  // 缓存器  let buffer1 = new ArrayBuffer(buffersize)  // 每次读取的字节个数  let len = 0  // 总共要读取的字节个数  let total = fileIo.statSync(srcfile.fd).size  // 偏移量  let off = 0  while (len = fileIo.readSync(srcfile.fd, buffer1, { offset: off, length: buffersize })) {    // 同步写入文件    fileIo.writeSync(destfile.fd, buffer1, { length: len })    // 更新偏移量    off += len    // 如果剩下的字节个数没有buffersize大 就更新buffersize    if (total - off < buffersize) {      buffersize = total - off    }  }  fileIo.closeSync(destfile.fd)})
复制代码


文档保存


文档保存并不牵涉到权限问题,可以直接操作。需要先在指定的目录下面创建一个新文件,然后获取该新文件的 URI,在打开该文件,写入字节,就实现了文件的创建和编写,相当于文档的保存了。



savedoc() {  // 文档选择器  let savepicker = new picker.DocumentViewPicker(this.context)  let option = new picker.DocumentSaveOptions();  // 创建新文件的名称  option.newFileNames = ['new.txt']  // 默认打开目录  option.defaultFilePathUri = 'file://docs/storage/Users/currentUser'  // 在用户系统新建一个文件  savepicker.save(option).then((result) => {    // 读出raw中文件的内容    let buffer1 = this.context.resourceManager.getRawFileContentSync('new.txt').buffer    // 写入的目标文件    let file = fileIo.openSync(result[0], fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY)    // 同步写入    fileIo.writeSync(file.fd, buffer1)  })}
复制代码


用户头像

高心星

关注

天将降大任于斯人也,必先苦其心志。 2024-10-17 加入

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。

评论

发布
暂无评论
HarmonyOS 5.0应用开发——用户文件操作_鸿蒙_高心星_InfoQ写作社区