当前位置: 首页 > article >正文

【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()


http://www.kler.cn/a/526252.html

相关文章:

  • 记录一次Sqoop从MySQL导入数据到Hive问题的排查经过
  • docker中运行的MySQL怎么修改密码
  • 在AWS上使用KMS客户端密钥加密S3文件,同时支持PySpark读写和Snowflake导入
  • 【C语言】static关键字的三种用法
  • 【电工基础】2.低压带电作业定义,范围,工作要求,电工基本工具
  • 抠图神器,全离线使用,支持win和mac
  • 前端AI— Language User Interface(语言用户界面,简称LUI)
  • 26_DropDown使用方法
  • C++并发编程指南08
  • 4 Spark Streaming
  • Vue3.0教程004:ref和reactive对比
  • 霍尔电流传感器
  • 【漫话机器学习系列】070.汉明损失(Hamming Loss)
  • 《DeepSeek 实用集成:大模型能力接入各类软件》
  • 【memgpt】letta 课程6: 多agent编排
  • 开源PDF分割合并工具 PDFsam Basic v5.3.0绿色版
  • 归并排序练习
  • 深入解析 JPA 实体生命周期回调
  • (0基础版,无需输入代码爬取)新手小白初步学习八爪鱼采集器
  • 图论——spfa判负环
  • 【ArcGIS微课1000例】0141:提取多波段影像中的单个波段
  • Hive:窗口函数[ntile, first_value,row_number() ,rank(),dens_rank()]和自定义函数
  • linux的/proc 和 /sys目录差异
  • [NVME] PMRCAP-Persistent Memory Region Capabilities
  • 10.4 字符编码和解码
  • 一文大白话讲清楚webpack进阶——8——Module Federation