PC文件适配最佳实践
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 |
否 |
支持选择的资源类型。比如:文件、文件夹和二者混合,仅对具有该系统能力的设备开放,默认值是文件类型。仅支持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 |
否 |
支持选择的资源类型。比如:文件、文件夹和二者混合,仅对具有该系统能力的设备开放,默认值是文件类型。仅支持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等接口,实现了增添文件、删除文件、查找指定类型文件、复制并移动文件、预览图片以及监听文件的功能。
参考示例:文件管理。
更多推荐
所有评论(0)