简介

okRcp是鸿蒙(Harmony)系统三方网络请求框架,包含okRcp和okAgent两个模块,分别基于Rcp和request.agent进行的二次封装。okRcp在基础请求之上增加了普通文件下载和上传功能,okAgent是为文件上传下载设计的专用模块,支持文件断点续传下载功能以及文件Hash校验功能。RCP相对于http和axios模块,支持取消请求和证书校验等功能。

2.1.0更新内容:

增加Json回调,支持直接返回json对象
修复请求成功后的强制参数断言
修复请求回调错误重复执行的bug

2.0.0更新内容:

增加websocket模块,支持自动重试和心跳检测

安装

ohpm install okrcp

三方库地址:

OpenHarmony三方库中心仓https://ohpm.openharmony.cn/#/cn/detail/okrcp

使用示例

在EntryAbility的onCreate方法中添加初始化代码

/**
 * 初始化全局配置,通过session构建器
 */
okRcp.client().init(new okRcp.SessionConfigBuilder()
  .setConnectTimeout(10000) //连接超时
  .setTransferTimeout(5000) //传输超时
  .setInterceptors(new DefaultInterceptor()) //设置默认拦截器
  .build()
).setRetryCount(2); //设置全局重试次数,共请求三次

/**
 * 通过原始配置初始化
 */
okRcp.client().init({
  requestConfiguration: {
    transfer: {
      timeout: {
        connectMs: 60000,
        transferMs: 60000
      }
    },
    security: {
      tlsOptions: {
        tlsVersion: 'TlsV1.2'
      }
    }
  }
});

设置自定义session

let session: rcp.Session = rcp.createSession(config);
okRcp.client().init()
  .setSession(session);

Get请求示例

okRcp.get<string>('https://www.baidu.com')
.execute(new okRcp.StringCallback({
  onSuccess: (response: okRcp.Response<string>) => {
    console.log(TAG, response.body());
  },
  onError: (response: okRcp.Response<string>) => {
    console.log(TAG, response.statusCode(), response.getMessage())
  }
}))

Post请求示例

okRcp.post<string>('https://www.baidu.com')
  .headers('Content-Type', 'application/json') //设置请求头
  .params('key', 'value') //设置参数
  .connectTimeout(10000) //单独设置连接超时
  .transferTimeout(10000) //单独设置传输超时
  .retryCount(2) //失败重试次数
  .loading(context) //显示进度对话框
  .tag('post_tag') //设置标签
  .execute(new okRcp.StringCallback({
    onSuccess: (response: okRcp.Response<string>) => {
  	console.log(TAG, response.body());
    },
    onError: (response: okRcp.Response<string>) => {
  	console.log(TAG, response.statusCode(), response.getMessage())
    }
}))


//取消请求
okRcp.cancel('post_tag');

//取消所有请求
okRcp.cancelAll();

直接返回json对象示例

//定义一个通用请求模板
export interface Result<T> {
  status: number;
  msg: string;
  data?: T;
}

//假设返回数据为User结构
interface User {
  id: string;
  name: string;
  age: number;
}

//调用请求
okRcp.post<Result<User>>('http://')
  .execute(new okRcp.JsonCallback({
    onSuccess: (response: okRcp.Response<Result<User>>) => {
      let result = response.body(); //获取js对象
      //此处的result不能作为对象使用,需做转换
      //let bean = jsonToBean(result);
      let user = result.data;
      if (user !== undefined) {
        //拿到用户接口
        console.log('user', user.id, user.name, user.age);
      }
    },
    onError: (response: okRcp.Response<Result<User>>) => {
      console.log('json', response.getMessage())
    }
  }))

设置集合示例

  let list = new List<string>();
  list.add('value');

  let map = new Map<string, okRcp.ParamValue>();
  map.set('key', 'value');

  okRcp.post<Result<User>>('http://')
	.params('list', list) //添加List
	.mapParams(map) //添加Map
	.execute(new okRcp.JsonCallback({
	  onSuccess: (response: okRcp.Response<Result<User>>) => {
		//...
	  }
	}))

Post上传文件测试

let path = getDownloadDir() + '/wx.apk';
okRcp.post<string>(uploadUrl)
  .progressInterval(1000)
  .params('userId', 'ts1456890650')
  .addFile('file', path, '微信') //添加上传文件
  // .addFileParams('files', { //添加多个文件
  //   remoteFileName: '微信.apk',
  //   contentOrPath: path
  // })
  .multipart(true) //多表单,如果添加了文件,则自动为true
  .execute(new okRcp.StringCallback({
    onSuccess: (response: okRcp.Response<string>) => {
        console.log(TAG, '上传成功');
    },
    onError: (response: okRcp.Response<string>) => {
        console.log(TAG, '上传失败', response.getMessage());
    },
    onUploadProgress: (progress: BaseProgress) => {
        console.log(TAG, '上传进度', Math.floor(progress.percent) + ' %', okUtils.formatSize(progress.speed) + '/s');
    },
    onDownloadProgress: (progress: BaseProgress) => {
        console.log(TAG, '下载进度', Math.floor(progress.percent) + ' %',
    okUtils.formatSize(progress.speed) + '/s');
    },
    onCancel:()=>{
        console.log(TAG, '上传取消');
    }
}))    

上传Json示例

  okRcp.post<string>(uploadUrl)
.tag('postJson')
.putJson(userBean) //上传json数据
.execute(new okRcp.StringCallback({
  onSuccess: () => {
    console.log(TAG, '成功')
  },
  onError: ()=>{
    console.log(TAG, '失败')
  }
}))

下载文件示例

const qqFileUrl = 'https://dldir1v6.qq.com/qqfile/qq/QQNT/Windows/QQ_9.9.25_251203_x64_01.exe';
const filePath = Environment.getUserDownloadDir() + '/qq.exe'; //保存路径
okRcp.download(qqFileUrl, filePath)
.tag(InitPage)
.loading(context, {
  message: '正在下载...',
  cancelableOnBack: true, //按back键可以取消,默认为true,可省略
})
.progressInterval(500) //进度更新回调间隔
.downloadTimeout(60000) //设置下载超时,未设置时不限制
.callback({
  onSuccess: (response: okRcp.FileResponse) => {
    console.log(TAG, '下载成功');
  },
  onProgress: (request: okRcp.DownloadRequest, progress: BaseProgress) => {
    console.log(TAG, Math.floor(progress.percent) + ' %', okUtils.formatSize(progress.speed) + '/s');
  },
  onError: (response: okRcp.Response<okRcp.File>) => {
    console.log(TAG, '下载失败,err=' + response.getMessage())
  },
  onCancel: () => {
    console.log(TAG, '用户取消下载');
  }
})
.start();

上传文件示例

  okRcp.upload(uploadUrl, '/storage/Users/currentUser/Download/wx.apk')
  .callback({
  onSuccess: (response: okRcp.FileResponse) => {
  console.log(TAG, '上传成功');
  },
  onError: (response: okRcp.FileResponse) => {
  console.log(TAG, '上传失败', response.getMessage());
  }
  })
  .start();

使用Agent模块下载和上传文件

/**
* Agent下载文件示例
  */

let context = this.getUIContext();
let uiAbilityContext = context.getHostContext() as common.UIAbilityContext;

const fileUrl = 'https://dldir1v6.qq.com/qqfile/qq/QQNT/Windows/QQ_9.9.25_251203_x64_01.exe';

okAgent.downloadFile(context)
.url(fileUrl, uiAbilityContext.cacheDir + '/QQ.apk')
.tag('downloadTest')
.start();

/**
* Agent下载文件,带config原始配置
  */
  okAgent.downloadFile(context)
  .loading(context)
  .config({
  action: request.agent.Action.DOWNLOAD,
  url: fileUrl,
  saveas: uiAbilityContext.cacheDir + '/QQ123.apk' //这里不能使用公共目录,只能用内部目录
  })
  .callback({
  onSuccess: () => {
  Dbg.console('下载成功')
  },
  onFailed: (task: okAgent.Task, response: okAgent.Response) => {
  Dbg.console('下载失败', response.message);
  }
  })
  .start();

Agent下载文件完整功能,带文件续传和哈希校验

okAgent.downloadFile(context)
.loading(context)
.config(new okAgent.DownloadBuilder()
  .url(fileUrl)
  .savePath(uiAbilityContext.cacheDir + '/QQ.apk')
  .overwrite(true) //覆盖目标文件
  .build())
.setContinueMode(true) //断点续传
.setSourceSize(282292392) //设置源文件大小
.setSourceMd5('4018A80403129EEC8374DBF2B2CE1710') //设置源文件哈希-md5
//.setSourceHash('4018A80403129EEC8374DBF2B2CE1710', Algorithm.MD5) //设置哈希类型
.setSourceSha256('21EF4C0CC88C42FAD3B8D15433AEE3700A53AA9510E9540D6031A1506F85FD21') //设置源文件sha256
.callback({
  onSuccess: () => {
    console.log(TAG, '下载成功')
  },
  onFailed: (task: okAgent.Task, response: okAgent.Response) => {
    console.error(TAG, '下载失败', response.message);
  },
  onProgress: (task: okAgent.Task, progress: okAgent.Progress) => {
    console.log(TAG, Math.floor(progress.percent) + ' %', okUtils.formatSize(progress.speed) + '/s');
  },
  onCancel: () => {
    console.log(TAG, '下载取消');
  }
})
.tag(InitPage)
.start();

Agent上传文件

okAgent.uploadFile(context,
new okAgent.UploadBuilder()
  .url(uploadUrl) //上传地址
  .params('userId', '21489514567540190573684') //设置账号id
  .addFile('file', uiAbilityContext.cacheDir + '/weixin.apk') //添加文件
  .method('POST') //设置请求方法
  .multipart(true) //使用多表单
  .build())
.tag('uploadTest') //设置标签
.callback({
  onSuccess: (task: okAgent.Task, response: okAgent.Response) => {
    console.log('onSuccess', response.statusCode.toString(), response.message)
  },
  onFailed: (task: okAgent.Task, response: okAgent.Response) => {
    console.error('onFailed', response.statusCode.toString(), response.message)
  },
  onProgress: (task: okAgent.Task, progress: okAgent.Progress) => {
    console.log('onProgress ', `${progress.percent} %, ${okUtils.formatSize(progress.speed)} /s`);
  }
}).start();

webSocket调用示例

/**
   * 创建webSocket连接
   */
  socket = okWeb.newSocket('wss://xxx.com/' + token)
  socket
	.tag('socket')
	//设置监听
	.listener({
	  onOpen: (data: Object) => {
		console.log('连接打开')
	  },
	  onClose: (closeResult: webSocket.CloseResult) => {
		console.log('连接关闭', closeResult.reason)
	  }
	})
	//设置重连间隔
	.setRetryInterval(60000)
	//设置心跳
	.setHeartbeat(30000, () => {
	  //此处填写需要发送的心跳消息
	  return '';
	});
  socket.connect(); //连接

  /**
   * 发送消息
   */
  socket.send('msg').then((result: boolean) => {
	//发送成功
  }).catch((err: BusinessError) => {
	//发送失败
  })

  /**
   * 发送消息
   */
  socket.send('msg', (err: BusinessError, result: boolean) => {
	if (result) {
	  //发送成功
	} else {
	  //发送失败
	}
  })


  //关闭连接
  socket.close({
	reason: 'fromUser' //设置关闭原因
  });

  //根据Tag关闭连接
  okWeb.close('socket');
  //关闭所有连接
  okWeb.closeAll();

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐