【NEXT】网络编程——上传文件(不限于jpg/png/pdf/txt/doc等),或请求参数值是file类型时,调用在线服务接口

最近在使用华为AI平台ModelArts训练自己的图像识别模型,并部署了在线服务接口。供给客户端(如:鸿蒙APP/元服务)调用。

import核心能力:

import { http } from '@kit.NetworkKit';
import { fileIo } from '@kit.CoreFileKit';

一、先用测试工具调用在线服务接口,是否成功

 

接口接收到传入的图片文件,识别图片内容后成功返回结果。

注意:接口要求输入的参数名是images,值类型是文件file。

二、从手机相册选取一张图片,并复制到沙箱缓存中

/**
   * 将文件拷贝到缓存中
   * @param from 原文件地址(拍照/相册)
   * @param to 目标文件地址(缓存)
   */
  copyFile(from: string, to: string): void {
    let fFile = fileIo.openSync(from);
    let tFile = fileIo.openSync(to, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); // 替换或创建文件
    fileIo.copyFileSync(fFile.fd, tFile.fd);
    fileIo.closeSync(fFile);
    fileIo.closeSync(tFile);
  }

三、读取已复制到缓存中的文件内容

/**
   * 读取文件内容
   * @param cacheImgUri:沙箱缓存文件地址
   * @returns
   */
  readFileContent(cacheImgUri: string): ArrayBuffer {
    let fFile = fileIo.openSync(cacheImgUri, fileIo.OpenMode.READ_ONLY);
    let fStat = fileIo.lstatSync(cacheImgUri);
    let arrayBufFile: ArrayBuffer = new ArrayBuffer(fStat.size); // 文件大小
    fileIo.readSync(fFile.fd, arrayBufFile);
    fileIo.fsyncSync(fFile.fd);
    fileIo.closeSync(fFile);
    return arrayBufFile;
  }

四、构建请求体body的内容

/**
   * 构建请求体body
   * @param boundary 分隔符
   * @param fileName 文件名
   * @param fileContent 文件内容
   * @returns 
   */
  buildBodyContent(boundary: string, fileName: string, fileContent: Uint8Array): ArrayBuffer {
    let txtEncoder = new util.TextEncoder();

    // 构建请求体前面内容
    let bodyPre = `--${boundary}\r\n`
    bodyPre = bodyPre + `Content-Disposition: form-data; name="images"; filename="${fileName}"\r\n`;
    bodyPre = bodyPre + 'Content-Type: application/octet-stream\r\n';
    bodyPre = bodyPre + '\r\n';
    let arrayPre = txtEncoder.encodeInto(bodyPre);

    // 构建请求体后面内容
    let bodyAft = '\r\n'
    bodyAft = bodyAft + `--${boundary}`
    bodyAft = bodyAft + '--\r\n'
    let arrayAft = txtEncoder.encodeInto(bodyAft);

    let body = buffer.concat([arrayPre, fileContent, arrayAft]); // 拼接请求体
    return body.buffer;
  }

五、按钮click事件调用aiAnalyseImg方法,发送请求在线服务接口

/**
   * 调用病虫害模型AI能力分析图片
   * @param imgUri 原图片地址(拍照/相册)
   * @returns 
   */
  async aiAnalyseImg(imgUri: string): Promise<void> {
    // 华为云ModelArts平台病虫害模型
    console.debug('正在分析的图片地址:' + imgUri); // 从相册选取的图片地址

    // 文件名
    let fileName = imgUri.split('/').pop() as string;
    let cacheFilePath = `${getContext().cacheDir}/${fileName}`;
    this.copyFile(imgUri, cacheFilePath);

    // 从沙箱缓存中读取文件内容
    let fileContent: Uint8Array = new Uint8Array(this.readFileContent(cacheFilePath));

    // 构建请求体body
    let boundary: string =
      '--------' + (await systemDateTime.getCurrentTime(true)).toString();
    let bodyContent = this.buildBodyContent(boundary, fileName, fileContent);
    hilog.debug(0x0000, 'aiAnalyseImg', 'hilog输出bodyContent:' + bodyContent);
    hilog.debug(0x0000, 'aiAnalyseImg', 'hilog输出bodyContent大小:' + bodyContent.byteLength);

    // 请求地址:modelArts平台在线服务API接口
    let url: string =
      'https://b07b6d6054****96d5e4420****e.apig.cn-north-4.huaweicloudapis.com/v1/infers/c91****8-c678-4e73-****-37c****3a';
    let request = http.createHttp();
    let reqOpts: http.HttpRequestOptions = { // 设置请求参数
      method: http.RequestMethod.POST,
      header: {
        'X-Apig-AppCode': '40d29da14dbd87abe3484f6fa0e1b07767d5226540459dbf8620a8f7', // 模型平台AppCode
        'Content-Type': `multipart/form-data;boundary=${boundary}`,
        'Content-Length': bodyContent.byteLength.toString(),
      },
      extraData: bodyContent,
    };
    // 发起请求
    request.request(url, reqOpts)
      .then((resp) => { // 请求成功,解析返回结果
        // TODO: 解析返回结果
        hilog.debug(0x0000, 'aiAnalyseImg', 'hilog输出结果:' + JSON.stringify(resp.result));
      })
      .catch((err: BusinessError) => {
        hilog.error(0x0000, 'aiAnalyseImg', 'catch输出错误:' + err.message);
      })

  }

注意:

1.构建请求体body中的Content-Type: application/octet-stream  与  header中设置的Content-Type: multipart/form-data

2.header参数中记得设置Content-Length: bodyContent.byteLength.toString()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964068.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏引擎 Unity - Unity 下载与安装

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

结构体DMA串口接收比特错位

发送&#xff1a; 显示&#xff1a; uint16_t接收时候会比特错位。

在线知识库的构建策略提升组织信息管理效率与决策能力

内容概要 在线知识库作为现代企业信息管理的重要组成部分&#xff0c;具有显著的定义与重要性。它不仅为组织提供了一个集中存储与管理知识的平台&#xff0c;还能够有效提升信息检索的效率&#xff0c;促进知识的创新和利用。通过这样的知识库&#xff0c;企业可以更好地应对…

e2studio开发RA2E1(4)----GPIO输出

e2studio开发RA2E1.4--GPIO输出 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置GPIO口配置R_IOPORT_PinWrite()函数原型R_IOPORT_PortWrite()函数原型代码 概述 本篇文章主要介绍如何使用e2studio对瑞萨单片机进行GP…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之用户登录

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【Spring篇】【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;1.登录-持久层 &…

51单片机看门狗系统

在 STC89C52 单片机中&#xff0c;看门狗控制寄存器的固定地址为 0xE1。此地址由芯片厂商在硬件设计时确定&#xff0c;但是它在头文件中并未给出&#xff0c;因此在使用看门狗系统时需要声明下这个特殊功能寄存器 sfr WDT_CONTR 0xE1; 本案将用一个小灯的工作状况来展示看门…

【C语言入门】解锁核心关键字的终极奥秘与实战应用(三)

目录 一、auto 1.1. 作用 1.2. 特性 1.3. 代码示例 二、register 2.1. 作用 2.2. 特性 2.3. 代码示例 三、static 3.1. 修饰局部变量 3.2. 修饰全局变量 3.3. 修饰函数 四、extern 4.1. 作用 4.2. 特性 4.3. 代码示例 五、volatile 5.1. 作用 5.2. 代码示例…

springCload快速入门

原作者&#xff1a;3. SpringCloud - 快速通关 前置知识&#xff1a; Java17及以上、MavenSpringBoot、SpringMVC、MyBatisLinux、Docker 1. 分布式基础 1.1. 微服务 微服务架构风格&#xff0c;就像是把一个单独的应用程序开发为一套小服务&#xff0c;每个小服务运行在自…

Unity Shader Graph 2D - 跳动的火焰

在游戏中&#xff0c;火焰是一种常见的特效。通常来讲火焰特效通过粒子系统的方式实现的相对较多&#xff0c;本文将通过Shader Graph的方式来实现一种不同的火焰效果。 那么怎么实现呢 首先创建一个名为Fire的Shader Graph文件&#xff0c;然后创建一个名为M_Fire的材质球。 …

【工欲善其事】利用 DeepSeek 实现复杂 Git 操作:从原项目剥离出子版本树并同步到新的代码库中

文章目录 利用 DeepSeek 实现复杂 Git 操作1 背景介绍2 需求描述3 思路分析4 实现过程4.1 第一次需求确认4.2 第二次需求确认4.3 第三次需求确认4.4 V3 模型&#xff1a;中间结果的处理4.5 方案验证&#xff0c;首战告捷 5 总结复盘 利用 DeepSeek 实现复杂 Git 操作 1 背景介绍…

CommonJS

CommonJS 是由 JavaScript 社区于 2oo9 年提出的包含模块、文件、IO、控制台在内的一系列标准。Node.js 的实现中采用了 CommonJS 标准的一部分&#xff0c;并在其基础上进行了一些调整。我们所说的 CommonJS 模块和 Node.js 中的实现并不完全一样&#xff0c;现在一般谈到 Com…

AP单类平均准确率

P_true N_true P_pred TP Fp N_pred FN TNP NTP&#xff08;真正样本&#xff0c;与真实框IoU大于阈值的框&#xff09; FP&#xff08;假正样本&#xff0c;与真实框IoU小于阈值的框&#xff09; TN&#xff08;真负样本&#xff0c;背景&#xff09;…

MQTT实战之在vue和java中使用

在VUE中使用MQTT 1、创建vue项目&#xff08;使用node版本为20.12.0&#xff09; >>npm create vitelatest Need to install the following packages: create-vite6.1.1 Ok to proceed? (y) y √ Project name: ... mqtt-vue √ Select a framework: Vue √ Select a v…

oracle: 表分区>>范围分区,列表分区,散列分区/哈希分区,间隔分区,参考分区,组合分区,子分区/复合分区/组合分区

分区表 是将一个逻辑上的大表按照特定的规则划分为多个物理上的子表&#xff0c;这些子表称为分区。 分区可以基于不同的维度&#xff0c;如时间、数值范围、字符串值等&#xff0c;将数据分散存储在不同的分区 中&#xff0c;以提高数据管理的效率和查询性能&#xff0c;同时…

数据分析系列--⑥RapidMiner构建决策树(泰坦尼克号案例含数据)

一、资源下载 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 2.划分训练集和测试集 3.应用模型 4.结果分析 一、资源下载 点击下载数据集 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 虽然决策树已经构建,但对于大多数初学者或…

Unity游戏(Assault空对地打击)开发(4) 碰撞体和刚体的添加

前言 飞机和世界的大小关系不太对&#xff0c;我稍微缩小了一下飞机。 详细步骤 选中所有地形对象&#xff0c;如果没有圈起的部分&#xff0c;点击Add Component搜索添加。 接着选中Player对象&#xff0c;添加这两个组件&#xff0c;最好&#xff08;仅对于本项目开发&#x…

【Windows7和Windows10下从零搭建Qt+Leaflet开发环境】

Windows7和Windows10下从零搭建QtLeaflet开发环境 本文开始编写于2025年1月27日星期一&#xff08;农历&#xff1a;腊月二十八&#xff0c;苦逼的人&#xff0c;过年了还在忙工作&#xff09;。 第一章 概述 整个开发环境搭建需要的资源&#xff1a; 操作系统 Windows7_x6…

【游戏设计原理】97 - 空间感知

一、游戏空间的类型 将游戏设计中的空间设计单独提取出来&#xff0c;可以根据其结构、功能和玩家的交互方式划分为以下几种主要类型。这些类型可以单独存在&#xff0c;也可以组合使用&#xff0c;以创造更加复杂和有趣的游戏体验。 1. 线性空间 定义&#xff1a;空间设计是…

基于云计算、大数据与YOLO设计的火灾/火焰目标检测

摘要&#xff1a;本研究针对火灾早期预警检测需求&#xff0c;采用在Kaggle平台获取数据、采用云计算部署的方式&#xff0c;以YOLO11构建模型&#xff0c;使用云计算服务器训练模型。经训练&#xff0c;box loss从约3.5降至1.0&#xff0c;cls loss从约4.0降至1.0&#xff0c;…

【大数据技术】教程03:本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …