1. API使用指导

文件操作主要涉及Core File Kit(文件基础服务)提供的接口进行文件的选择,保存,持久化等操作。若应用需要通过自定义的文件选择器访问路径,则需要使用访问控制模块提供的授权申请能力获取权限。

1.1 Core File Kit

1.1.1 文件URI

FileUri

文件的URI,根据问卷路径不同URI会有所区别:

应用沙箱uri:file://<bundleName>/<sandboxPath>;

公共目录文件类uri:file://docs/storage/Users/currentUser/<publicPath>;

公共目录媒体类uri:file://media/<mediaType>/IMG_DATATIME_ID/<displayName>;

getUriFromPath

通过传入的路径path生成应用自己的uri(不支持媒体类型uri的获取);将path转uri时,路径中的中文及非数字字母的特殊字符将会被编译成对应的ASCII码,拼接在uri中。

参考链接:@ohos.file.fileuri (文件URI)

1.1.2 选择器

select

通过选择模式拉起documentPicker界面,用户可以选择一个或多个文件。接口采用callback异步返回形式,传入参数DocumentSelectOptions对象,返回选择文件的uri数组。

save

通过保存模式拉起documentPicker界面,用户可以保存一个或多个文件。接口采用Promise异步返回形式,传入可选参数DocumentSaveOptions对象,返回保存文件的uri数组。

参考链接:@ohos.file.picker (选择器)

1.1.3 文件分享

persistPermission

异步方法对所选择的多个文件或目录URI持久化授权,以promise形式返回结果,该接口仅对具有该系统能力的设备开放。

revokePermission

异步方法对所选择的多个文件或目录uri取消持久化授权,以promise形式返回结果,该接口仅对具有该系统能力的设备开放。

activatePermission

异步方法使能多个已经永久授权过的文件或目录,以promise形式返回结果,该接口仅对具有该系统能力的设备开放。

deactivatePermission

异步方法取消使能授权过的多个文件或目录,以promise形式返回结果,该接口仅对具有该系统能力的设备开放。

checkPersistentPermission

异步方法校验所选择的多个文件或目录URI持久化授权,以promise形式返回结果。

参考链接:@ohos.fileshare (文件分享)

1.1.4 Core File Kit涉及的参考文档

参考链接:FileUri开发指导(C/C++)选择用户文件授权持久化

1.2 访问控制

三方应用需要访问公共目录时,需通过弹窗授权向用户申请授予 Download 目录权限、Documents 目录权限或 Desktop 目录权限。

参考链接:获取并使用公共目录

1.3 AbilityKit

三方应用可通过接口,由系统从已安装的应用中寻找符合要求的应用,打开特定文件。

参考链接:目标方接入步骤

2. 文件操作场景指导及示例

2.1 选择用户文件

2.1.1 通过filepicker提供的select方法拉起指定目录

通过select函数拉起文件管理提供的filepicker。通过filepicker中的DocumentSelectOptions参数,可以指定以下内容:

名称

类型

必填

说明

maxSelectNumber

number

选择文件最大个数,上限500,有效值范围1-500(选择目录仅对具有该系统能力的设备开放。且目录选择的最大个数为1)。默认值是1。系统能力:SystemCapability.FileManagement.UserFileService

defaultFilePathUri

string

指定选择的文件或者目录路径。

fileSuffixFilters

Array

选择文件的后缀类型,传入字符串数组,每一项代表一个后缀选项,每一项内部用"|"分为两部分,第一部分为描述,第二部分为过滤后缀。没有"|"则没有描述,该项整体是一个过滤后缀。每项过滤后缀可以存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔,传入数组长度不能超过100。仅对具有该系统能力的设备开放。默认全部过滤,即显示所有文件。系统能力:SystemCapability.FileManagement.UserFileService

selectMode

DocumentSelectMode

支持选择的资源类型。比如:文件、文件夹和二者混合,仅对具有该系统能力的设备开放,默认值是文件类型。仅支持2in1设备。系统能力:SystemCapability.FileManagement.UserFileService.FolderSelection

authMode

boolean

拉起授权picker,默认为false(非授权模式)。当authMode为true时为授权模式,defaultFilePathUri必填,表明待授权uri。仅支持2in1设备。系统能力:SystemCapability.FileManagement.UserFileService.FolderSelection

拉起文档目录示例

以下示例指定了拉起filepicker时的默认路径为Document路径,同时指定了可选择的文件后缀。选择完成后,该应用会在Document目录下生成test1文件夹。

//... 
public PullDocPicker() {
   try {
      let documentSelectOptions = new picker.DocumentSelectOptions();
      documentSelectOptions.defaultFilePathUri = 'file://docs/storage/Users/currentUser/Documents/'
      documentSelectOptions.selectMode = picker.DocumentSelectMode.MIXED;
      documentSelectOptions.fileSuffixFilters =
         ['文字/Word格式(*.doc *docx)|*.doc,*docx', '.*', '.docx', '.doc', '.pptx', '.ppt'];
      documentSelectOptions.fileSuffixFilters = []
      let documentPicker = new picker.DocumentViewPicker();
      documentPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
         hilog.info(0x0000, FilePickerManager.TAG_LOG, 'FilePickerManager documentSelectResult uri %{public}s',
            JSON.stringify(documentSelectResult));
         fs.mkdir('/storage/Users/currentUser/Documents/test1')
      }).catch((err: BusinessError) => {
         hilog.info(0x0000, FilePickerManager.TAG_LOG, 'DocumentViewPicker.select failed with err %{public}s',
            JSON.stringify(err));
      });
   } catch (error) {
      let err: BusinessError = error as BusinessError;
      hilog.info(0x0000, FilePickerManager.TAG_LOG, 'DocumentViewPicker failed with err %{public}s',
         JSON.stringify(err));
   }
}
//...

效果示例

2.1.2 通过startAbility方法拉起指定目录

可以调用startAbility接口拉起filepicker,并指定拉起的默认路径。

拉起用户根目录示例

//...
public PullCustomPicker() {
   let want: Want = {
     deviceId: '',
     bundleName: 'com.huawei.hmos.filemanager',
     abilityName: 'MainAbility'
   };
   want.parameters = {
     'fileUri': 'file://docs/storage/Users/currentUser'
   };
   let context = getContext(this) as common.UIAbilityContext;
   context.startAbility(want, (error: BusinessError) => {
     hilog.info(0x0000, FilePickerManager.TAG_LOG, 'PullCustomPicker failed with err %{public}s',
       JSON.stringify(error));
   })
 }
//...

效果示例

2.1.3 申请3D目录权限

公共目录获取接口仅用于获取公共目录路径,不对公共目录访问权限进行校验。若需访问公共目录需申请对应的公共目录访问权限。三方应用需要访问公共目录时,需通过弹窗授权向用户申请授予 Download 目录权限、Documents 目录权限或 Desktop目录权限,具体参考访问控制-向用户申请授权

"requestPermissions" : [
   "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY",
   "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY",
   "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY",
]

获取文档目录权限示例

//在应用窗口拉起时进行权限的申请,实际场景下可以在需要的时候再通过requestPermission操作申请
onWindowStageCreate(windowStage: window.WindowStage): void {
   //...
   const permissions: Array<Permissions> = ['ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY'];
   permissionManager.getInstance().checkPermissions(permissions,this.context);
   //SLEEPING
 }
//...
public async checkPermissions(permissions: Array<Permissions>, context: common.UIAbilityContext) {
  let grantStatus: abilityAccessCtrl.GrantStatus = await this.checkPermissionGrant(permissions[0]);
  if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
    // 已经授权,可以继续访问目标操作
    hilog.info(0x0000, PermissionManager.TAG_LOG, 'checkPermissions', 'already granted');
  } else {
    // 申请权限
    this.reqPermissionsFromUser(permissions,context);
  }
}
//...
public reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
    atManager.requestPermissionsFromUser(context, permissions).then((data) => {
      let grantStatus: Array<number> = data.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        if (grantStatus[i] === 0) {
          // 用户授权,可以继续访问目标操作
        } else {
          // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
          atManager.requestPermissionOnSetting(context, ['ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY']).then((data: Array<abilityAccessCtrl.GrantStatus>) => {
            hilog.info(0x0000, PermissionManager.TAG_LOG, 'reqPermissionsFromUser', 'data:' + JSON.stringify(data));
          }).catch((err: BusinessError) => {
            hilog.info(0x0000, PermissionManager.TAG_LOG, 'reqPermissionsFromUser', 'data:' + JSON.stringify(err));
          });
          return;
        }
      }
      // 授权成功
    }).catch((err: BusinessError) => {
      console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
      hilog.info(0x0000, PermissionManager.TAG_LOG, 'checkPermissions', 'already granted');
    })
  }

效果示例

2.2 保存用户文件

2.2.1 通过filepicker提供的save方法保存文件

通过save函数拉起文件管理提供的filepicker。通过filepicker中的DocumentSaveOptions参数,可以指定以下内容:

名称

类型

必填

说明

maxSelectNumber

number

选择文件最大个数,上限500,有效值范围1-500(选择目录仅对具有该系统能力的设备开放。且目录选择的最大个数为1)。默认值是1。系统能力:SystemCapability.FileManagement.UserFileService

defaultFilePathUri

string

指定选择的文件或者目录路径。

fileSuffixFilters

Array

选择文件的后缀类型,传入字符串数组,每一项代表一个后缀选项,每一项内部用"|"分为两部分,第一部分为描述,第二部分为过滤后缀。

没有"|"则没有描述,该项整体是一个过滤后缀。每项过滤后缀可以存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔,传入数组长度不能超过100。仅对具有该系统能力的设备开放。默认全部过滤,即显示所有文件。

系统能力:SystemCapability.FileManagement.UserFileService

selectMode

DocumentSelectMode

支持选择的资源类型。比如:文件、文件夹和二者混合,仅对具有该系统能力的设备开放,默认值是文件类型。仅支持2in1设备。系统能力:SystemCapability.FileManagement.UserFileService.FolderSelection

authMode

boolean

拉起授权picker,默认为false(非授权模式)。当authMode为true时为授权模式,defaultFilePathUri必填,表明待授权uri。仅支持2in1设备。系统能力:SystemCapability.FileManagement.UserFileService.FolderSelection

保存文件示例:

//... 
public SaveFileByPicker() {
   try {
     let desktopDirUri: string = 'file://docs/storage/Users/currentUser/Desktop/';
     let documentSaveOptions = new picker.DocumentSaveOptions();
     documentSaveOptions.newFileNames = ['1.txt'];
     documentSaveOptions.defaultFilePathUri = desktopDirUri;  
     documentSaveOptions.pickerMode = picker.DocumentPickerMode.DEFAULT;
     let documentPicker = new picker.DocumentViewPicker();
     documentPicker.save(documentSaveOptions).then((documentSaveResult: Array<string>) => {
       hilog.info(0x0000, FilePickerManager.TAG_LOG, 'FilePickerManager documentSaveResult uri %{public}s',
         JSON.stringify(documentSaveResult));
     }).catch((err: BusinessError) => {
       hilog.info(0x0000, FilePickerManager.TAG_LOG, 'SaveFileByPicker.select failed with err %{public}s',
         JSON.stringify(err));
     });
   } catch (error) {
     let err: BusinessError = error as BusinessError;
     hilog.info(0x0000, FilePickerManager.TAG_LOG, 'SaveFileByPicker failed with err %{public}s',
       JSON.stringify(err));
   }
 }
//...

效果示例:

2.3 持久化授权

需要持久化授权能力的主要场景如下:

场景

典型应用示例

先使用A应用打开B文件后,关闭A应用。再次打开A应用时,通过历史记录打开B文件。

通过应用侧的历史记录打开文档。

使用IM类应用A接收/发送文件后,双击使用应用B打开文件浏览编辑。

打开通过QQ发送的word文档。

在A应用的文件中插入附件/超链接后,双击附件/超链接使用应用B打开。

打开亿图图示中的超链接。

通过拖拽/复制粘贴添加到A应用中的文件尝试通过B应用打开。

打开通过拖拽/复制粘贴到QQ中发送的文件。

注意事项

应用卸载后,本应用做过的持久化授权会被删除。如果卸载应用保留历史记录,在重新安装应用后,做过持久化授权的历史文件将没有权限访问,需要重新授权。

2.3.1 对路径进行持久化授权

在以上描述的场景中,需要调用persistPermission接口对文件或者目录的路径进行持久化授权,从而确保应用可以在之后用到时可以持有访问的权限。文件持久化能力需要获取FILE_ACCESS_PERSIST权限。权限申请流程参考访问控制-申请应用权限

//module.json5
//...
"requestPermissions": [
   {
   "name": "ohos.permission.FILE_ACCESS_PERSIST",
   }
//...

持久化授权示例:

//... 
private CustomPersistPermission(targetUri: string, targetMode: fileShare.OperationMode) {
   let policyInfo: fileShare.PolicyInfo = {
     uri: targetUri,
     operationMode: targetMode,
   };
   let policies: Array<fileShare.PolicyInfo> = [policyInfo];
   fileShare.persistPermission(policies).then(() => {
     hilog.info(0x0000, FilePickerManager.TAG_LOG, '%{public}s', 'CustomPersistPermission successfully');
   }).catch((err: BusinessError<Array<fileShare.PolicyErrorResult>>) => {
     hilog.info(0x0000, FilePickerManager.TAG_LOG, 'CustomPersistPermission failed with err %{public}s',
       JSON.stringify(err));
   });
 }

2.3.2 激活已经持有的持久化授权

已经进行持久化授权的文件或路径,在每一次需要访问前,需要激活已经持有的持久化权限。

//... 
private CustomActivatePermission(targetUri: string, targetMode: fileShare.OperationMode) {
   let policyInfo: fileShare.PolicyInfo = {
     uri: targetUri,
     operationMode: targetMode,
   };
   let policies: Array<fileShare.PolicyInfo> = [policyInfo];
   fileShare.activatePermission(policies).then(() => {
     hilog.info(0x0000, FilePickerManager.TAG_LOG, '%{public}s', 'CustomActivatePermission successfully');
   }).catch((err: BusinessError<Array<fileShare.PolicyErrorResult>>) => {
     hilog.info(0x0000, FilePickerManager.TAG_LOG, 'CustomActivatePermissionfailed with err %{public}s',
       JSON.stringify(err));
   });
 }

2.3.3 取消已经持有的持久化授权

已经进行持久化授权的文件或路径,可以通过以下方式取消。

//...
private CustomRevokePermission(targetUri: string, targetMode: fileShare.OperationMode) {
  let policyInfo: fileShare.PolicyInfo = {
    uri: targetUri,
    operationMode: targetMode,
  };
  let policies: Array<fileShare.PolicyInfo> = [policyInfo];
  fileShare.revokePermission(policies).then(() => {
    hilog.info(0x0000, FilePickerManager.TAG_LOG, '%{public}s', 'CustomRevokePermission successfully');
  }).catch((err: BusinessError<Array<fileShare.PolicyErrorResult>>) => {
    hilog.info(0x0000, FilePickerManager.TAG_LOG, 'CustomRevokePermission failed with err %{public}s',
      JSON.stringify(err));
  });
}

2.3.4 取消已经激活的持久化授权

已经激活了持久化授权的文件或路径,可以通过以下方式取消激活状态。

//...
private CustomDeactivatePermission(targetUri: string, targetMode: fileShare.OperationMode) {
  let policyInfo: fileShare.PolicyInfo = {
    uri: targetUri,
    operationMode: targetMode,
  };
  let policies: Array<fileShare.PolicyInfo> = [policyInfo];
  fileShare.deactivatePermission(policies).then(() => {
    hilog.info(0x0000, FilePickerManager.TAG_LOG, '%{public}s', 'CustomDeactivatePermission successfully');
  }).catch((err: BusinessError<Array<fileShare.PolicyErrorResult>>) => {
    hilog.info(0x0000, FilePickerManager.TAG_LOG, 'CustomDeactivatePermission failed with err %{public}s',
      JSON.stringify(err));
  });
}

2.4 跨应用预览用户文件

以下应用类型存在跨应用预览用户文件的场景:

IM类应用:发送文件/接收文件后,尝试使用其他应用预览/编辑文件。文档类应用:文件以附件/超链接形式存在,尝试使用其他应用预览/编辑文件。

2.4.1 通过filepicker插入文件场景

通过系统提供的filepicker能力插入文件后,应用即可获取该文件的临时访问权限。在进行持久化授权后,即可分享给其他应用打开该文件。以下代码示例在选择文件后,进行了读权限的持久化授权,并分享给预览应用打开文件。在实际应用场景中,可以灵活指定需要的权限和需要分享给的目标应用。

//...
let uriTemp: string = '';
try {
  // 1.拉起系统picker
  let documentSelectOptions = new picker.DocumentSelectOptions();
  let documentPicker = new picker.DocumentViewPicker;
  documentPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
    uriTemp = documentSelectResult[0];
    hilog.info(0x0000, FileShareManager.TAG_LOG, 'SharePublicFile documentSelectResult uri %{public}s', uriTemp);
    // 2.持久化授权
    let policyInfo: fileShare.PolicyInfo = {
      uri: uriTemp,
      operationMode: fileShare.OperationMode.READ_MODE,
    };
    let policies: Array<fileShare.PolicyInfo> = [policyInfo];
    fileShare.persistPermission(policies).then(() => {
      hilog.info(0x0000, FileShareManager.TAG_LOG, 'SharePublicFile persistPermission successfully');
    }).catch((err: BusinessError<Array<fileShare.PolicyErrorResult>>) => {
      hilog.info(0x0000, FileShareManager.TAG_LOG,
        'SharePublicFile persistPermission failed with error message %{public}s', JSON.stringify(err));
    });
    // 3.分享文件
    let want: Want = {
      // 配置被分享文件的读写权限,例如对被分享应用进行读写授权
      flags: wantConstant.Flags.FLAG_AUTH_WRITE_URI_PERMISSION | wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION,
      // 只配置读权限 flags:wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION,
      // 配置分享应用的隐式拉起规则 action: 'ohos.want.action.sendData',
      action: 'ohos.want.action.viewData',
      uri: uriTemp,
      type: 'application/pdf'
    }
    let context = getContext(this) as common.UIAbilityContext;
    context.startAbility(want, (error: BusinessError) => {
      hilog.info(0x0000, FileShareManager.TAG_LOG, 'SharePublicFile result code %{public}s', JSON.stringify(error));
    })
  }).catch((err: BusinessError) => {
    hilog.info(0x0000, FileShareManager.TAG_LOG, 'SharePublicFile.select failed with err %{public}s',
      JSON.stringify(err));
  });
} catch (error) {
  let err: BusinessError = error as BusinessError;
  hilog.info(0x0000, FileShareManager.TAG_LOG, 'SharePublicFile failed with err %{public}s',
    JSON.stringify(err));
}

2.4.2 通过拖拽插入文件场景

通过拖拽插入文件后,应用即可获取该文件的临时访问权限。在进行持久化授权后,即可分享给其他应用打开该文件。

参考demo:

import { uniformDataStruct, uniformTypeDescriptor, unifiedDataChannel } from '@kit.ArkData';
import { fileUri, fileIo as fs } from '@kit.CoreFileKit'
import { common } from '@kit.AbilityKit'

@Entry
@Component
struct Index {
  @State ondrop_uri: string = '';
  @State description:string = '';
  uiContext = this.getUIContext();
  udKey: string = '';
  build() {
    Column() {
      Column() {
        Text("拖出方")
        Text("oriUri:" + 'file://data/image/1.png')
        Text("description:" + 'This is the description of the hyperlink')
      }
      .width(300)
      .height(200)
      .borderWidth(2)
      .margin(20)
      .onDragStart((event)=>{

        //创建FILE_URI类型数据
        let fileUriDetails : Record<string, string> = {
          'attr1': 'value1',
          'attr2': 'value2',
        }
        let fileUri : uniformDataStruct.FileUri = {
          uniformDataType : 'general.file-uri',
          oriUri : 'file://data/image/1.png',
          fileType : 'general.image',
          details : fileUriDetails,
        }

        //创建HYPERLINK类型数据
        let hyperlink : uniformDataStruct.Hyperlink = {
          uniformDataType:'general.hyperlink',
          url : 'file://data/image/1.png',
          description : 'This is the description of the hyperlink',
        }

        //新建一个新的unifiedData
        let unifiedData = new unifiedDataChannel.UnifiedData();
        //新建一个UnifiedRecord 初始化塞入FORM类型的数据(可自定义)
        let record = new unifiedDataChannel.UnifiedRecord(uniformTypeDescriptor.UniformDataType.HYPERLINK, hyperlink);
        //addEntry 添加另一份FILE_URI数据到record里面
        record.addEntry(uniformTypeDescriptor.UniformDataType.FILE_URI, fileUri);
        //将record塞入unifiedData
        unifiedData.addRecord(record);
        //将unifiedData塞入dragEvent
        event.setData(unifiedData)
      })

      Button("Reset")
        .onClick(()=>{
          this.ondrop_uri = ''
          this.description = ''
        })

      Column() {
        Text("落入方")
        Text("oriUri:" + this.ondrop_uri)
        Text("description:" + this.description)
      }
      .width(300)
      .height(200)
      .borderWidth(2)
      .margin(20)
      .onDrop((event)=>{
        //配置异步拖拽参数
        let context = this.uiContext.getHostContext() as common.UIAbilityContext;
        let pathDir: string = context.distributedFilesDir;
        let destUri = fileUri.getUriFromPath(pathDir);

        //配置数据处理回调
        let progressListener: unifiedDataChannel.DataProgressListener = (progress: unifiedDataChannel.ProgressInfo, dragData: UnifiedData|null) => {
          if(dragData != null) {
            //拿到records
            let records:Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords();
            //循环遍历查询
            for (let i = 0; i < records.length; i++) {
              let unifiedDataRecord = records[i] as unifiedDataChannel.UnifiedRecord;
              //找到对应类型的数据 getEntry
              let fileUriRead : uniformDataStruct.FileUri = unifiedDataRecord.getEntry(uniformTypeDescriptor.UniformDataType.FILE_URI) as uniformDataStruct.FileUri;
              if (fileUriRead != undefined) {
                //拿到数据类型中对应的字段
                console.info(`oriUri: ${fileUriRead.oriUri}`);
                this.ondrop_uri = fileUriRead.oriUri;
              }
              let hyperlink = unifiedDataRecord.getEntry(uniformTypeDescriptor.UniformDataType.HYPERLINK) as uniformDataStruct.Hyperlink;
              if (hyperlink != undefined) {
                console.info(`description: ${hyperlink.description}`);
                this.description = hyperlink.description as string;
              }
            }
          } else {
            console.log('dragData is undefined');
          }
          console.log(`percentage: ${progress.progress}`);
        };

        //配置异步获取数据options
        let options: DataSyncOptions = {
          destUri: destUri,
          fileConflictOptions: unifiedDataChannel.FileConflictOptions.OVERWRITE, //配置数据冲突处理方式
          progressIndicator: unifiedDataChannel.ProgressIndicator.DEFAULT,  //配置进度条,数据处理超过500ms生效
          dataProgressListener: progressListener,
        }
        try {
          this.udKey = (event as DragEvent).startDataLoading(options);
          console.log('udKey: ', this.udKey);
        } catch(e) {
          console.log(`startDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
        }
      }, {disableDataPrefetch: true}) //当使用startDataLoading获取数据时需设置该参数为true,防止拖拽提前获取数据。

      Button('取消数据传输')
        .onClick(() => {
          try {
            this.getUIContext().getDragController().cancelDataLoading(this.udKey);
          } catch (e) {
            console.log(`cancelDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
          }
        })
        .margin({top: 10})

    }
    .height('100%')
    .width('100%')
  }
}

2.4.3通过剪贴板插入文件场景

通过剪贴板插入文件后,应用即可获取该文件的临时访问权限。在进行持久化授权后,即可分享给其他应用打开该文件。

2.5 文件格式关联

2.5.1 打开特定后缀的文件场景

应用作为特定文件格式打开的目标方,适配已达到可以在打开方式中被选择的目的。

参考链接:目标方接入步骤

2.5.2 注册右键扩展菜单场景

三方应用可以接入文件管理内右键菜单,并指定操作。在应用工程对应的待注册右键菜单的模块的module.json5文件中,在”module”下新增子节点”fileContextMenu”,配置值为指定的右键配置文件,示例如下:

//module.json5
//...
"module":{
    "name": "entry",
    "type": "entry",
    "mainElement": "EntryAbility",
    "fileContextMenu": "$profile:menu",
//...

此含义为右键配置文件在此模块的resources\base\profile目录下,文件名为menu.json。右键菜单的注入方式核心重点主要是配置文件的编写,配置文件的名字当前无限制,只要和第一步中指定的文件名保持一致即可,放置位置也需要按照配置指定目录存放,即开发视图的resources\base\profile目录下。

下表为配置文件标签说明

属性名称

含义

数据类型

是否可缺省

fileContextMenu

标识当前module注册右键菜单的数量。

(单模块和单应用注册数量不能超过5个,

配置超过数量文管当前只解析随机5个)

对象数组

不可缺省

下表为rightMenu标签配置说明

属性名称

含义

数据类型

是否可缺省

abilityName

表示当前右键菜单对应的需要拉起的ability名称

字符串

不可缺省

menuItem

右键菜单显示的文件信息

资源id

不可缺省

menuHandler

一个ability可以创建多个右键菜单, 用该字段来区分用户拉起的不同右键菜单项。

该字段在用户点击右键菜单执行时,会作为参数传递给右键菜单应用

字符串

不可缺省

menuContext

定义展示该菜单项需要的上下文,可以支持多种情况, 类型为数组

对象数组

不可缺省

下表为menuContext标签配置说明

属性名称

含义

数据类型

是否可缺省

menuKind

表示什么情况下触发该右键菜单 0:空白处 1:文件 2:文件夹 3:文件和文件夹

数值

不可缺省

menuRule

用来表示是单选/多选下选择单个文件/文件夹,或者两种情况都显示。

单选:single,多选:multi单选+多选:both(全小写)

字符串

不可缺省,当menuKind为1或2读取

fileSupportType

当选中的文件列表里包含这些文件类型时, 显示该右键菜单

字符串数组

不可缺省,仅menuKind为1时候读取,为*才读取下面的字段,如果为具体值,不读取下面字段,如果为空,这条策略废弃

fileNotSupportType

当选中的文件列表里包含这些文件类型时, 不显示该右键菜单

字符串数组

仅menuKind为1,且fileSupportType为*才读取该字段

配置示例

//menu.json
//...
  {
   "fileContextMenu": [
      {
            "abilityName":"abilityName",
            "menuItem":"$string:menu1" ,
            "menuHandler": "openPDF", 
            "menuContext": [
          {   
                  "menuKind" : 1, 
                  "menuRule": "single",
                  "fileSupportType": ["*"], //menukind=1文件时生效,优先取白名单,若第一个为真实白名单值,不再读取黑名单
                  "fileNotSupportType": [".rar",".zip"]  //黑名单,menukind=1文件时生效,若fileSupportType为空,不读取fileNotSupportType       
            },{   
                  "menuKind" : 1, 
                  "menuRule": "Multi",
              "fileSupportType": [".docx",".doc"]
             },{   
                  "menuKind" : 2
             },{   
                  "menuKind" : 3
             }]
      }, 
      {
            "abilityName":"abilityName",
            "menuItem":"$string:menu1" ,
            "menuHandler": "openPPT", 
            "menuContext": [{   
                  "menuKind" : 1, 
                  "menuRule": "single",
                  "fileSupportType": ["*"], //menukind=1文件时生效,优先取白名单,若第一个为真实白名单值,不再读取黑名单
                  "fileNotSupportType": [".rar",".zip"]  //黑名单,menukind=1文件时生效,若fileSupportType为空,不读取fileNotSupportType       
             },{   
                  "menuKind" : 1, 
                  "menuRule": "multi",
              "fileSupportType": [".docx",".doc"]
             },{   
                  "menuKind" : 2
             },{   
                  "menuKind" : 3
             }]
      }, 
  ]
  }
 //...

效果示例

2.5.3 注册文管内右键新建文件场景

三方应用可以接入文件管理内右键菜单的新建文件能力。同右键扩展菜单一致,新增配置文件,放在resources\base\profile目录下,和右键扩展菜单共用同一个文件,但是配置文件内容需要在另外编写,可以基于右键扩展菜单的配置文件继续添加,也可以单独只包含新建文件的配置项。

//module.json5
...
"newFile": [
    {
      "menuName": "demotxt",
      "menuIcon": "black_logo.png",
      "fileType": ".txt",
      "fileContent": "template/demo.txt"
    }
  ]
...

menuIcon和fileContent的默认目录在resources\rawfile路径下。

一级配置文件标签说明

属性名称

含义

数据类型

是否可缺省

newFile

标识当前module注册新建文件的数量。(单模块和单应用注册数量不能超过5个)

对象数组

不可缺省

newFile标签配置说明

属性名称

含义

数据类型

是否可缺省

menuName

表示在文管右键新建文件上具体显示的内容,如:“文本文档”

资源id

不可缺省

MenuIcon

新建文件的图标路径

字符串

不可缺省

fileType

新建的文件格式类型

字符串

不可缺省

fileContent

新建文件的模板路径

字符串

不可缺省

效果示例

2.6 删除文件到回收站

当前系统不支持三方应用直接将文件从系统中移除,可以调用deleteToTrash接口将文件移动到回收站。

import { fileManagerService } from '@kit.FileManagerServiceKit';
import { BusinessError } from '@kit.BasicServicesKit';

async function deleteFile() {
  // 以内置存储目录为例
  // 示例代码targetUri表示Download目录下文件
  // 开发者应根据自己实际获取的uri进行开发,并确保对该文件有读写权限
  let targetUri: string = "file://docs/storage/Users/currentUser/Download/1.txt";
  try {
    let trashUri: string = await fileManagerService.deleteToTrash(targetUri);
    console.info("trashUri: " + trashUri);
  } catch (err) {
    let error: BusinessError = err as BusinessError;
    console.error("delete failed, errCode:" + error.code + ", errMessage:" + error.message);
  }
}

参考链接:fileManagerService

2.7 下载文件

用于下载网络文件到本地目录的场景。

2.7.1 通过下载控件快速保存至公共目录

参考链接:icon形式使用arkUI控件download模式保存指导

2.7.2 设置默认保存路径至公共目录

参考文档:获取并使用公共目录

2.7.3 通过路径选择器保存至公共目录

参考文档:通过路径选择器保存文件

3. 完整demo参考

示例使用@ohos.file.picker@ohos.file.fs 等接口,实现了picker拉起文档编辑保存、拉起系统相册图片查看、拉起视频并播放的功能。

参考示例:选择并查看文档与媒体文件

文件管理

本示例主要展示了文件管理相关的功能,使用@ohos.filemanagement.userFileManager 、@ohos.fileio 、@ohos.file.fs等接口,实现了增添文件、删除文件、查找指定类型文件、复制并移动文件、预览图片以及监听文件的功能。

参考示例:文件管理

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐