HarmonyOS 鸿蒙Next上传文件权限问题。Failed to open/read local data from file/application

发布于 1周前 作者 gougou168 来自 鸿蒙OS

HarmonyOS 鸿蒙Next上传文件权限问题。Failed to open/read local data from file/application

protected  postFiles(params: string = ‘’,filesPath:string, httpUrl: string,callBack:Function) {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpPostUrl = this.appUrl + httpUrl;
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
// 从API 8开始,使用on(‘headersReceive’, Callback)替代on(‘headerReceive’, AsyncCallback)。 8+
httpRequest.on(‘headersReceive’, (header) => {
console.info('header: ’ + JSON.stringify(header));
});
httpRequest.request(
// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
httpPostUrl,
{
method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
// 开发者根据自身业务需要添加header字段
header: {
‘Content-Type’: ‘multipart/form-data’
},
// 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定
extraData: params,
expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型
usingCache: true, // 可选,默认为true
priority: 1, // 可选,默认为1
connectTimeout: 60000, // 可选,默认为60000ms
readTimeout: 60000, // 可选,默认为60000ms
usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
usingProxy: false, // 可选,默认不使用网络代理,自API 10开始支持该属性
caPath: ‘/path/to/cacert.pem’, // 可选,默认使用系统预制证书,自API 10开始支持该属性
clientCert: {
// 可选,默认不使用客户端证书,自API 11开始支持该属性
certPath: ‘/path/to/client.pem’, // 默认不使用客户端证书,自API 11开始支持该属性
keyPath: ‘/path/to/client.key’, // 若证书包含Key信息,传入空字符串,自API 11开始支持该属性
certType: http.CertType.PEM, // 可选,默认使用PEM,自API 11开始支持该属性
keyPassword: “passwordToKey” // 可选,输入key文件的密码,自API 11开始支持该属性
},
multiFormDataList: [// 可选,仅当Header中,'content-Type’为’multipart/form-data’时生效,自API 11开始支持该属性
{
name: “file1”, // 数据名,自API 11开始支持该属性
contentType: ‘multipart/form-data’, // 数据类型,自API 11开始支持该属性
filePath:filesPath,
remoteFileName: ‘fileName.txt’ // 可选,自API 11开始支持该属性
}
]
}, (err: BusinessError, data: http.HttpResponse) => {
if (!err) {
// data.result为HTTP响应内容,可根据业务需要进行解析
console.info(‘Result:’ + JSON.stringify(data.result));
console.info(‘code:’ + JSON.stringify(data.responseCode));
// data.header为HTTP响应头,可根据业务需要进行解析
console.info(‘header:’ + JSON.stringify(data.header));
console.info(‘cookies:’ + JSON.stringify(data.cookies)); // 8+
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
callBack(data);
} else {
console.error(‘error:’ + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off(‘headersReceive’);
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
}
);
}

//我前端是用pickerController选择一个图片上传。 但是现在报错Failed to open/read local data from file/application

这里的filesPath 为 file://media/Photo/7/IMG_1730661092_006/cb0728b3a1774994b6c36f7fefa3bcd7.jpeg  为什么会报我没有权限?

我picker不是弹出来了么 还要什么权限? 我感觉我这个也没问题啊。。 求指教。

5 回复

相册图片是没法做直接上传处理的,只能上传沙箱路径的图片,所以需要先将文件读取到沙箱路径

我写的子线程上传示例

mediaUrl就是你上面的那个相册地址

context = getContext(this) as common.UIAbilityContext
cacheDir = this.context.cacheDir
/**
* TaskPool 任务函数
* */
[@Concurrent](/user/Concurrent)
async function uploadFile(mediaUrl: string, cacheDir: string, baseUrl: string, context: Context) {

let formData = new FormData()

try {
let path = mediaUrl
const resFile = fs.openSync(path, fs.OpenMode.READ_ONLY)
let newPath = cacheDir + "/" + resFile.name;
fs.copyFileSync(resFile.fd, newPath)
let realUri = "internal://cache/" + resFile.name;
formData.append(`file`, realUri)

// let configuration: Configuration = JSON.parse(MMKVUtils.getDefaultMMKV().decodeString('config'))
// let baseUrl = configuration.host_other.crms + "/" + CrmsApiConstants.UPLOAD_FILE

let result = await new Promise<CrmsUploadResponse>((resolve, reject) => {
// 发送请求
axios.post<string, AxiosResponse<string>, FormData>(baseUrl, formData, {
headers: {
'Content-Type': 'multipart/form-data',
'tenantId': BuildProfile.tenantid,
},
context: context,
onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
console.info(progressEvent && progressEvent.loaded && progressEvent.total ?
Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
},
}).then((res: AxiosResponse<string>) => {
let result = JSON.stringify(res.data);
let response: CrmsUploadResponse = JSON.parse(result)
resolve(response)
}).catch((err: AxiosError) => {
console.error("error:" + JSON.stringify(err));
})
})

return result

} catch (e) {
return ""
}
}

非常感谢 确实是这样不过你是用realUri进行上传 我用这个失败了,我直接使用newPath进行的上传。现在成功了。 let path = filesPath const resFile = fileIo.openSync(path, fileIo.OpenMode.READ_ONLY) let newPath = getContext(this).cacheDir + “/” + resFile.name; fileIo.copyFileSync(resFile.fd, newPath) let realUri = “internal://cache/” + resFile.name;

手头有真机吗,可以用真机试一下

看到个帖子是同一个问题,说是模拟器会出现这种问题

https://developer.huawei.com/consumer/cn/forum/topic/0203161037857151668?fid=0109140870620153026

没有真机啊。 我看说是catch目录的问题 现在解决了 需要先拷贝到缓存目录 然后上传。

在HarmonyOS鸿蒙Next系统中遇到上传文件权限问题时,首先需要确认几个关键点:

  1. 权限声明:确保你的应用已在config.json文件中正确声明了所需的文件读写权限,如ohos.permission.READ_EXTERNAL_STORAGEohos.permission.WRITE_EXTERNAL_STORAGE

  2. 动态权限请求:对于敏感权限,如读写外部存储,应用需要在运行时动态请求用户授权。确保你的代码中有相应的逻辑来请求这些权限,并妥善处理用户拒绝授权的情况。

  3. 文件路径问题:检查你尝试访问的文件路径是否正确。如果是访问应用私有目录下的文件,通常不需要额外权限;但如果是访问公共目录或外部存储,则需要相应的权限。

  4. 应用沙箱机制:HarmonyOS有严格的应用沙箱机制,确保应用无法随意访问其他应用的文件。如果你的应用需要访问特定文件,请确保这些文件是应用自己创建或通过合法途径获得的。

  5. 日志分析:查看详细的错误日志,分析Failed to open/read local data from file/application的具体原因,可能是权限不足、路径错误或文件本身不存在等问题。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部