1 关键字

fileAccessHelper,文件移动,USB/TF

2 问题描述

开发板型号:RK3568

系统版本:Openharmony 3.2.13.5

问题现象:调用fileAccessHelper.move方法将移动设备内的文件移动至设备内,接口调用失败,报错信息为:errCode:14300002,errMessage:Invalid uri

测试步骤:

  1. 下载每日构建的 rk3568镜像 烧录设备

  2. 插入USB/TF卡,创建应用并申请文件操作相关的权限后,使用下面的代码执行测试。

let uri = "xxx"; // usb 文件 uri
let fileName = "xxx"; // 复制后文件名称
let context = getContext(this) as common.UIAbilityContext;
let pathDir = context.filesDir + '/' + fileName;
let fileAccessHelper:fileAccess.FileAccessHelper = this.getFileAccesssHelper();

try {
    let fileUri = await fileAccessHelper.move(uri, pathDir);
} catch (error) {
    console.error("move failed, errCode:" + error.code + ", errMessage:" + error.message);
};

3 问题原因

公共文件访问框架提供的move方法在调用时对文件路径和目标位置路径进行了校验,如果不是在同一设备内,抛出异常。

3.1 正常机制

  • 文件的移动操作为正常的业务需求,在具备权限的情况下应该能正常进行文件的移动。

3.2 异常机制

  • 调用公共文件访问框架提供的move方法,移动文件到其他设备内出错。

4 解决方案

在参考公共文件访问框架的文件移动操作发现其使用fileio进行文件的操作,fileio的部分接口在api9之后不再维护,官方推荐使用filefs,因此使用@ohos.file.fs (文件管理)模块读取文件数据,然后将数据保存到其他的设备内,实现文件的复制后再删除源文件,从而实现文件的移动,参考代码如下:

let uri = "xxx"; // usb 文件 uri
let fileName = "xxx"; // 复制后文件名称
let context = getContext(this) as common.UIAbilityContext;
let pathDir = context.filesDir + '/' + fileName;
let fileAccessHelper:fileAccess.FileAccessHelper = this.getFileAccesssHelper();

fileAccessHelper.openFile(uri, fileAccess.OPENFLAGS.WRITE_READ).then((fd)=>{
    // 读写或者创建权限
    fs.open( pathDir, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file)=>{
        // 申请空间500M
        let buf = new ArrayBuffer(524288000);
        // 读取文件数据
        fs.read(fd, buf).then((readLen) => {
            // 文件的实际大小,可以根据这个裁剪buf
            console.log(`readLen:${readLen}`);
            // 将数据写入文件
            fs.write(file.fd, buf).then((writeLen)=>{
                // 关闭文件
                fs.closeSync(file.fd);
                fs.closeSync(fd);
                // 删除原文件
                fs.unlinkSync(uri);
            })
        })
    })
});

5 定位过程

  1. 根据报错编码14300002定位move方法中报错的代码位置foundation/filemanagement/user_file_service/services/file_extension_hap/entry/src/main/ets/FileExtensionAbility/FileExtensionAbility.ts

img

报错编码14300002被定义为常量E_URIS

img

  1. 注意到move接口使用checkUri方法对源文件和目标路径地址进行了校验,查看checkUri代码:

img

这里校验uri是否以datashare://开头,而应用的沙箱路径均为/data开头,因此接口调用失败。

6 知识分享

公共文件访问框架的部分接口是使用fileio提供的能力实现的,因此有一些文件操作可以直接使用fileio或者filefs进行操作。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐