HarmonyOS 鸿蒙Next 打开相机或相册获取图片路径及文件上传时设置路径打开文件报错 openPicker {"code":13900002}

发布于 1周前 作者 h691938207 最后一次编辑是 5天前 来自 鸿蒙OS

【关键字】 openPicker / 13900002 / lstatSync / fileio

【问题描述】 打开相机或者相册获取图片后路径,获取文件上传,设置路径打开文件时候报错 openPicker {“code”:13900002}。

以下是调用关键代码:

const permissions: Array<Permissions> = [ 'ohos.permission.READ_MEDIA'
];
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
//查看是否有权限
reqPermissionsFromUser(permissions, context,getContext(this)).then((res)=>{
let jurisdictionStatus = res
if(jurisdictionStatus){//有权限
//可以选择的张数
let length = this.maxLength - this.fileList.length
openPicker(getContext(this),length).then((res)=>{
//图片上传处理
this.images(res)
})

}else{
console.log('无权限=====')
}
});

下边是工具类关键代码:

//获取权限
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { picker } from '@kit.CoreFileKit';
import fs from '@ohos.file.fs';
import { uploadModels } from '../Models/myModel';
import { camera, cameraPicker } from '@kit.CameraKit';
import { MyLog } from '@ohos/BaseComponentLibrary/Index';
import { ToastUtil } from '@ohos/BaseComponentLibrary/src/main/ets/utils/ToastUtil';

export async function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext,content:Context):Promise<boolean>{
let jurisdictionStatus:boolean = false
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
await 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) {
console.log('用户已授权')// 用户授权,可以继续访问目标操作
//chooseAlbum(content)
// openPicker(content)
jurisdictionStatus = true
} else {
jurisdictionStatus = false
ToastUtil.showToast('用户拒绝授权')
console.log('用户拒绝授权')// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
return;
}
}

// 授权成功
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
return jurisdictionStatus
}

// 弹出图片选择器方法
export async function openPicker(content:Context,maxLength:number) {
let photoUriList:uploadModels[] = []
try {
// 设置图片选择器选项
const photoSelectOptions = new picker.PhotoSelectOptions();
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
photoSelectOptions.maxSelectNumber = maxLength;//最大张数
// 创建并实例化图片选择器
const photoViewPicker = new picker.PhotoViewPicker();
// 选择图片并获取图片URI
let uris: picker.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions);
let newUrlList:uploadModels[] = []
if (!uris || uris.photoUris.length === 0){
photoUriList = []
}else{
uris.photoUris.forEach((item)=>{
MyLog.error("item---"+item)
let itemlList = item.split('.')
const fileType = itemlList[itemlList.length-1]
let list = itemlList[0].split('/')
// const fileName = list[list.length-1] + '.' + fileType
// 生成一个新的文件名 对名字格式有要求在此更改
const fileName = new Date().getTime() + '.' + fileType
// 打开文件读取流
// let file = fs.openSync(item, fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);
let file = fs.openSync(item, fs.OpenMode.READ_ONLY);
console.error('file fd: ' + file.fd);
let stat = fs.lstatSync(item);

MyLog.error("state---------"+stat.size+"----------")

// 获取当前上下文
let context = getContext(content) as common.UIAbilityContext;
// 新建一个保存裁剪后图片的路径
let newUrl = context.cacheDir + '/' + fileName;
console.log(context.cacheDir,newUrl,'是个什么路径')
// 复制图片到新的路径
fs.copyFileSync(file.fd, newUrl);
// 关闭文件读取流
fs.closeSync(file);
newUrlList.push({
fileName:fileName,
fileType:fileType,
filePath:item
})
})
photoUriList = newUrlList
}


// 更新状态变量:设置显示图片的URI
// content.imgUri = newUrl;
// 更新状态变量:保存原始图片的URI
// content.imgOriginal = uri;
// 图片更改时触发的方法
// this.imgChange();
} catch (e) {
console.error('openPicker', JSON.stringify(e));
}
return photoUriList
}

export async function chooseCamera(context:common.Context){
let photoUriList:uploadModels[] = []
try {
let pickerProfile: cameraPicker.PickerProfile = {
cameraPosition:camera.CameraPosition.CAMERA_POSITION_BACK
};
let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(context,[cameraPicker.PickerMediaType.PHOTO],pickerProfile)
console.log("成功获取图片"+ pickerResult.resultUri)
let itemlList = pickerResult.resultUri.split('.')
const fileType = itemlList[itemlList.length-1]
let list = itemlList[0].split('/')
const fileName = list[list.length-1] + '.' + fileType
photoUriList.push({
fileName:fileName,
fileType:fileType,
filePath:pickerResult.resultUri
})

} catch (error){
let err = error as BusinessError
console.log('失败 code' + err.code)
}
return photoUriList
}

【解决方案】 报错原因是因为lstatSync接口传入的路径必须是文件的应用沙箱路径。

相关参考:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-fileio-V5#fileiolstatsync7

1 回复

针对您提到的HarmonyOS 鸿蒙Next系统中打开相机或相册获取图片路径及文件上传时设置路径打开文件报错openPicker {"code":13900002}的问题,这通常与权限管理或文件路径处理不当有关。

首先,请确保您的应用已在manifest.json文件中声明了访问存储的权限,如ohos.permission.READ_MEDIA,并在运行时向用户请求了这些权限。若权限未正确申请或用户拒绝授权,将无法进行文件访问。

其次,检查您的代码是否正确处理了文件路径。在鸿蒙系统中,文件选择器返回的是文件URI,而非直接的文件路径。您需要根据这个URI创建文件对象,然后才能进行文件上传等操作。

若上述步骤无误,但问题依旧存在,可能是系统API的使用方式有误或存在其他未知问题。此时,建议您查阅最新的鸿蒙开发文档,或联系官网客服获取更专业的帮助。官网地址是:https://www.itying.com/category-93-b0.html

回到顶部