访问鸿蒙设备文件 原创
1 通过DevEco Studio访问设备文件
DevEco Studio内置设备文件管理工具Device File Browser,开发者可以在PC端进行文件新建、删除、上传下载等操作,当前支持普通文件视图与应用沙箱视图两种模式,主要使用场景如下:
- 查看设备上的文件列表及基本信息。
 - 在设备上搜索文件及文件夹。
 - 在设备上新建、删除文件。
 - 从PC本地上传文件到设备上,从设备上下载文件到PC本地。
 
该工具不支持对无权限的目录(如应用沙箱路径)进行增删改,详细操作指导请见访问设备文件。
公共目录/storage/media/100/local/files/Docs支持通过hdc直接上传与下载文件,应用沙箱目录不支持hdc,需通过bftpd命令行访问。
2 通过命令行工具访问应用沙箱
真机设备中内置了bftpd二进制软件,可以通过命令行的方式访问debug应用的沙箱目录。通过该方式可以与编译构建流水线结合,实现批量向应用内推送资源文件等操作。
更多内容请参见命令行方式访问应用沙箱。
3 通过Core File Kit访问和管理设备文件
应用文件包括应用安装文件、应用资源文件、应用缓存文件等,应用文件目录和一部分系统文件(应用运行必须使用的系统文件)组成了一个集合,该集合为应用沙箱目录,代表了应用可见的所有目录范围。
文件分类模型示意:
0900086000300134184.20201216095126.86523331460016843504112994983392.png
系统文件及其目录对于应用是只读的,应用仅能保存文件到应用文件目录下。
对于游戏类应用,需要用过picker组件来访问用户文件、媒体,访问应用文件目录可以通过应用上下文context获取文件路径。
3.1 应用文件访问与管理
开发者可从UIAbilityContext中获取HAP级别的文件路径,或者从ApplicationContext中获取APP级别的文件路径,再通过基础文件操作接口ohos.file.fs实现应用文件访问能力,具体开发指导请参见应用文件访问、ohos.file.fs文件管理API。
3.2 用户文件访问
用户需要分享文件、保存图片、视频等用户文件时,开发者可通过系统预置的文件选择器(FilePicker)实现该能力。通过Picker访问相关文件,将拉起对应的FilePicker应用,引导用户完成界面操作,接口本身无需申请权限。
3.2.1 选择文档/音频类文件
通过文件选择器DocumentViewPicker中的select()接口,拉起FilePicker应用界面进行文件选择。该接口返回的uri权限是临时只读权限,待应用退出后台后,获取的临时权限就会失效。开发者可定义全局变量保存uri,从而对返回结果做集中处理。
文档类uri的格式类型为:
'file://docs/storage/Users/currentUser/<relative_path>/test.txt'其中各个字段表示的含义为:
uri字段  | 说明  | 
file://docs/storage/Users/currentUser/  | 文件管理器的根目录。  | 
<relative_path>/  | 文件在根目录下的相对路径。例如:Download/和Documents/。  | 
test.txt  | 用户文件系统中存储的文件名,支持的文件类型为文件管理器支持的所有类型,以文件管理器为准。例如txt、jpg、mp4和mp3等格式的文件。  | 
获取uri后,可通过ohos.file.fs文件管理API对文件进行进一步处理。
3.2.2 选择图片/视频
游戏类应用无法申请相册管理模块读权限'ohos.permission.READ_IMAGEVIDEO',因此需通过PhotoAccessHelper模块的PhotoViewPicker选择本地相册的媒体文件。
媒体文件uri的格式类型为:
图片uri格式:file://media/Photo/[id]/IMG_datetime_0001/displayName.jpg
视频uri格式:file://media/Photo/[id]/VID_datetime_0001/displayName.mp4
音频uri格式:file://media/Audio/[id]/AUD_datetime_0001/displayName.mp3
其中各个字段表示的含义为:
uri字段  | 说明  | 
file://media  | 表示这个uri是媒体文件。  | 
Photo  | Photo表示这个uri是媒体文件中的图片或者视频类文件。  | 
Audio  | 表示这个uri是媒体文件中的音频类文件。  | 
[id]  | 表示在数据库中多个表中处理后的值,并不是指表中的file_id列,注意请不要使用此id去数据库中查询具体文件。  | 
IMG_datetime_0001  | 表示图片文件在用户文件系统中存储的文件名去掉后缀剩下的部分。  | 
VID_datetime_0001  | 表示视频文件在用户文件系统中存储的文件名去掉后缀剩下的部分。  | 
AUD_datetime_0001  | 表示音频文件在用户文件系统中存储的文件名去掉后缀剩下的部分。  | 
获得媒体uri后使用photoAccessHelper.getAssets接口获取对应uri的PhotoAsset对象。这种方式获取的对象可以调用getThumbnail获取缩略图和使用get接口读取PhotoKeys中的部分信息。
以下为PhotoKeys中支持临时授权方式可以读取的信息:
名称  | 值  | 说明  | 
URI  | uri  | 文件uri。  | 
PHOTO_TYPE  | media_type  | 媒体文件类型。  | 
DISPLAY_NAME  | display_name  | 显示名字。  | 
SIZE  | size  | 文件大小。  | 
DATE_ADDED  | date_added  | 文件创建时的Unix时间戳(单位:秒)。  | 
DATE_MODIFIED  | date_modified  | 文件修改时的Unix时间戳(单位:秒)。修改文件名不会改变此值,当文件内容发生修改时才会更新。  | 
DURATION  | duration  | 持续时间(单位:毫秒)。  | 
WIDTH  | width  | 图片宽度(单位:像素)。  | 
HEIGHT  | height  | 图片高度(单位:像素)。  | 
DATE_TAKEN  | date_taken  | 拍摄时的Unix时间戳(单位:秒)。  | 
ORIENTATION  | orientation  | 图片文件的方向。  | 
TITLE  | title  | 文件标题。  | 
下面为通过临时授权方式使用媒体文件uri进行获取缩略图和读取文件部分信息的示例代码:
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { dataSharePredicates } from '@kit.ArkData';
// 定义一个uri数组,用于接收PhotoViewPicker选择图片返回的uri
let uris: Array<string> = [];
const context = getContext(this);
// 调用PhotoViewPicker.select选择图片
async function photoPickerGetUri() {
  try {  
    let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
    PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
    PhotoSelectOptions.maxSelectNumber = 1;
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {
      console.info('PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));
      uris = PhotoSelectResult.photoUris;
    }).catch((err: BusinessError) => {
      console.error('PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
    });
  } catch (error) {
    let err: BusinessError = error as BusinessError;
    console.error('PhotoViewPicker failed with err: ' + JSON.stringify(err));
  }
}
async function uriGetAssets() {
try {
    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
    let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
    // 配置查询条件,使用PhotoViewPicker选择图片返回的uri进行查询
    predicates.equalTo('uri', uris[0]);
    let fetchOption: photoAccessHelper.FetchOptions = {
      fetchColumns: [photoAccessHelper.PhotoKeys.WIDTH, photoAccessHelper.PhotoKeys.HEIGHT, photoAccessHelper.PhotoKeys.TITLE, photoAccessHelper.PhotoKeys.DURATION],
      predicates: predicates
    };
    let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOption);
    // 得到uri对应的PhotoAsset对象,读取文件的部分信息
    const asset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
    console.info('asset displayName: ', asset.displayName);
    console.info('asset uri: ', asset.uri);
    console.info('asset photoType: ', asset.photoType);
    console.info('asset width: ', asset.get(photoAccessHelper.PhotoKeys.WIDTH));
    console.info('asset height: ', asset.get(photoAccessHelper.PhotoKeys.HEIGHT));
    console.info('asset title: ' + asset.get(photoAccessHelper.PhotoKeys.TITLE));
    // 获取缩略图
    asset.getThumbnail((err, pixelMap) => {
      if (err === undefined) {
        console.info('getThumbnail successful ' + JSON.stringify(pixelMap));
      } else {
        console.error(`getThumbnail fail with error: ${err.code}, ${err.message}`);
      }
    });
  } catch (error){
    console.error('uriGetAssets failed with err: ' + JSON.stringify(error));
  }
}3.2.3 保存用户文件
对音频、图片、视频、文档类文件的保存操作类似,均通过调用对应Picker的save()接口并传入对应的saveOptions来实现。通过Picker访问相关文件,无需申请权限。
当前所有Picker的save接口都是用户可感知的,具体行为是拉起FilePicker, 将文件保存在系统文件管理器管理的特定目录,与图库管理的资源隔离,无法在图库中看到。
对于游戏类应用,若需保存图片、视频资源到图库,需使用相册管理模块的PhotoAccessHelper.showAssetsCreationDialog接口进行保存操作,该接口无需申请系统相册读取权限。
具体开发指导请参见保存用户文件
官方文档参考
原文链接:华为开发者文章
更多问题可关注:
鸿蒙游戏官方网站:已有游戏移植-鸿蒙游戏-华为开发者联盟
公开课:华为开发者学堂




















