《鸿蒙/Harmony | 开发日志》选择文件或拍照功能

鸿蒙选择文件或拍照的功能,有直接可以用的 API,而且和Android相比,最大的好处,是不需要向用户索要文件权限。

不需要索要权限的原因是,鸿蒙的权限改动升级的非常大,以前 Android的权限逻辑是,你授予了文件或图库的权限后,代码是可以在后台获取你所有的文件。这一点也是非常大的安全隐患。所以我自己用Android APP根本不敢随便授权那些 APP 给照片权限的,万一人家后台暗戳戳的扫码你的敏感图片,用户根本不知道的。

(这个权限的痛点,也是我使用最大的痛点。迫不及待的想升级鸿蒙。)

但是现在鸿蒙的文件权限逻辑是,没有办法可以直接获取文件库的权限,只有拉起的选择文件的界面,选择了几个文件,那么 APP 的代码就只能临时获取这几个文件的权限,APP 关闭再重新打开后,这些权限都消失了(当然有别的方式,可以存取这些临时的权限,网盘类的 APP 必须要这样),必须再次打开选择界面了。

选择文件 / 照片

一般在 APP 中选择文件大概分类三类

  1. 照片 + 拍照
  2. 视频 + 录像
  3. 文件(各种类型的文件、浏览器下载的文件等)

在鸿蒙中,这几类是不同的。

照片和视频,属性媒体类,而文件是系统文件类 。这上面三种都是需要调用不同的 API 来文件的。虽然获取文件的方式根据上面的类别不同调用的 API 不同,但是获取后文件的处理,是一样的。

照片 + 拍照

效果:

可以使用访问提供的 Picker API,选择照片并且自带拍照功能,参考官方文档《使用Picker选择媒体库资源

const options = new photoAccessHelper.PhotoSelectOptions();
options.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
options.maxSelectNumber = 1; // 获取多少张

const picker = new photoAccessHelper.PhotoViewPicker()
const result = await picker.select(options)

const uris = result.photoUris;

if (uris.length == 0) {
		return null // 没有选择文件
}

const imgURI = uris[0] // 获取的文件

在这里注意一下。官方文档描述了一段:

select返回的uri权限是只读权限,可以根据结果集中uri进行读取文件数据操作。注意不能在picker的回调里直接使用此uri进行打开文件操作,需要定义一个全局变量保存uri,使用类似一个按钮去触发打开文件。

文件 + 浏览器下载

访问自带选择文件的API《【鸿蒙官方文档】选择用户文件》,调用出来的界面,特别像 PC 端,浏览器打开的选择文件,可以多选,如下图:

const options = new picker.DocumentSelectOptions();
// 选择文档的最大数目(可选)
options.maxSelectNumber = 5;

const documentViewPicker = new picker.DocumentViewPicker(uiAbilityContext);

const uris = await documentViewPicker.select(options)


if (uris.length == 0) {
		return null // 没有选择文件
}

const fileURI = uris[0] // 获取的文件

在这里注意一下。官方文档描述了一段:

注意

1、使用picker获取的select()返回的uri权限是临时只读权限,待退出应用后台后,获取的临时权限就会失效。

2、如果想要获取持久化权限(仅在2in1设备上生效),请参考文件持久化授权访问

3、开发者可以根据结果集中uri做进一步的处理。建议定义一个全局变量保存uri。

多选的效果图:

选择视频 + 拍摄

目前官方文档提供了两种选择视频的方式。

  1. 使用《Picker选择媒体库资源》
  2. 使用《文件选择器》

在实践过程中,推荐还是第一种比较方便,第二种只能获取 APP 当前自带有权限的目录,如果没有传递授权目录,就会没有视频可以选,也没有拍摄的功能。

第一种和照片的接口一样,只是修改一下参数即可:

const options = new photoAccessHelper.PhotoSelectOptions();
options.MIMEType = photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE; // 过滤选择媒体文件类型为视频
options.maxSelectNumber = 1;

const picker = new photoAccessHelper.PhotoViewPicker()
const result = await picker.select(options)

效果如下图:

根据上一步获取到的uri,获取文件详细信息

可以使用《文件管理 API》和《文件URI API》来获取文件的信息。根据上面官方提示需要使用单独的按钮触发,才能去用api去打开文档。但是我本人实验过,是可以直接使用api来获取文件的信息的。

获取文件的名称

文件URI API》可以简单的获取文件的名称。

import { fileUri } from '@kit.CoreFileKit';

//imgURI 是上一步获取的文件uri file://media/xxx
let fileUriObject = new fileUri.FileUri(imgURI);
console.info("The name of FileUri is " + fileUriObject.name);

获取文件的大小

这个需要使用《文件管理 API》来获取。stat方法获取。注意直接调用stat方法传入上面的 imgURI的话,会报错,文件不存在。需要先使用open方法,获取文件的fd信息,在把fd传给stat方法,才能成功获取信息。

import { fileIo as fs } from '@kit.CoreFileKit';


const file = await fs.open(imgURI) 
const stat = await fs.stat(file.fd)  // file.fd 是个数字类似 153 这样的。不用明白这数字是干嘛的

console.log(stat.size)

获取文件的二进制

import { fileIo as fs } from '@kit.CoreFileKit';


const file = await fs.open(imgURI) 
const stat = await fs.stat(file.fd)  // file.fd 是个数字类似 153 这样的。不用明白这数字是干嘛的

let arrayBuffer = new ArrayBuffer(stat.size);
await fs.read(file.fd, arrayBuffer)

图片压缩

参考另一篇文章《鸿蒙/Harmony | 开发日志》图片压缩

参考

  1. 【鸿蒙官方文档】使用Picker选择媒体库资源
  2. 【鸿蒙官方文档】选择用户文件
  3. 【鸿蒙官方文档】文件管理 API
  4. 【鸿蒙官方文档】文件URI API
  5. 《鸿蒙/Harmony | 开发日志》图片压缩
posted @ 2024-09-18 16:14  xakoy  阅读(98)  评论(0编辑  收藏  举报