1. 开发环境

系统版本: OpenHarmony 4.1 release

DevEco Studio版本: OpenHarmony: DevEco Studio 4.1 Release(build: 4.1.0.400)

SDK版本: OpenHarmony: 4.1.7.8

 

2. 问题描述

直接用Image组件加载一个HTTPS图片地址,DevEco Studio预览是能看到的,一安装到手机端就报证书错误。报错信息为Http task of url xxx/xx.png failed, response code 0, msg from netStack: SSL peer certificate or SSH remote key was not OK。

问题代码:

Image('xx.png')
    .width('30%')
    .onError((err) => {
        console.info(`Invoke wparksdc failed, code is, message is ${err.message}`);
})

 

3. 定位思路

(1)根据错误提示,是Image组件加载网络资源时的证书有问题,导致加载失败,因此考虑解决证书问题。

(2)鉴于Image组件当前仅支持加载简单网络图片,以及不能配置capath字段等局限性,而传统的通过HTTP的session的方式去加载网络图片资源具有足够的稳定性和可靠性。因此,可以考虑先通过HTTP下载后Image组件加载的方式可作为我们处理类似问题的一个常用思路。

 

4. 解决方案

4.1 证书配置

HTTP请求使用默认证书验证失败,需要使用服务端证书做单向认证时,可通过HTTP原生接口能力的capath字段指定沙箱路径下证书。证书可通过如下步骤放入工程机:

(1)通过 “hdc file send testCert.pem(PC上证书路径)/etc/ssl/certs/testCert.pem(证书默认沙箱路径)”命令上传;

(2)将证书放入项目rawFile文件目录下,使用getRawFileContent读取内容,通过创建文件的方式写入,然后将capath指向当前写入路径。

参考示例:

let context: Context = getContext(this);
const keyPemComponent = context.resourceManager.getRawFileContentSync('testCa.pem')
let filesDir: string = context.filesDir
let filePath = filesDir + "/testCer.pem";
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.writeSync(file.fd, keyPemComponent.buffer);
fs.fsyncSync(file.fd);
fs.closeSync(file);

但鉴于Image组件当前仅支持加载简单网络图片,以及不能配置capath字段继而不能解决证书问题等局限性,若该方没有解决该问题,则应采用如下“HTTP方式下载图片”方案。

4.2 HTTP方式下载图片

通过单独http或者request下载能力下载图片后再加载到Image组件。

参考示例:

Image(this.imgUrl)
  .width('30%')
  .onError((err) => {
    console.info(`onError Invoke wparksdc failed, code is, message is ${err.message}`);
    if (this.imgUrl.startsWith('file://')) {
      return
    }
    let filePath = this.context.cacheDir + "/text.jpg"
    let config: request.agent.Config = {
      action: request.agent.Action.DOWNLOAD,
      mode: request.agent.Mode.BACKGROUND,
      url: this.imgUrl,
      overwrite: true,
      saveas: filePath,
      gauge: false
    };
    console.log(`filePath: ${filePath}`)
    request.agent.create(this.context, config).then((task: request.agent.Task) => {
      console.info(`Succeeded in creating a download task. result: ${task.tid} ${JSON.stringify(task.config)}`);
      task.on('completed', () => {
        this.imgUrl = fileUri.getUriFromPath(filePath)
      })
      task.start()
    }).catch((err: BusinessError) => {
      console.error(`Failed to create a download task, Code: ${err.code}, message: ${err.message}`);
    });
  })

 

Logo

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

更多推荐