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

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

import核心能力:

javascript 复制代码
import { http } from '@kit.NetworkKit';
import { fileIo } from '@kit.CoreFileKit';

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

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

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

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

javascript 复制代码
/**
   * 将文件拷贝到缓存中
   * @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);
  }

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

javascript 复制代码
/**
   * 读取文件内容
   * @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的内容

javascript 复制代码
/**
   * 构建请求体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方法,发送请求在线服务接口

javascript 复制代码
/**
   * 调用病虫害模型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()

相关推荐
ChinaDragonDreamer4 天前
HarmonyOS:创建应用静态快捷方式
harmonyos·鸿蒙
我能与泰森过两招6 天前
鸿蒙next 自定义日历组件
typescript·harmonyos·鸿蒙
SuperHeroWu710 天前
【HarmonyOS NEXT】鸿蒙三方应用跳转到系统浏览器
华为·harmonyos·鸿蒙·跳转·系统浏览器·openlink·三方应用
电子小子洋酱11 天前
基于EMQX+MQTT+ESP32+Openharmony的开发实例
单片机·嵌入式硬件·物联网·harmonyos·鸿蒙
89315196012 天前
《鸿蒙开发-鸿蒙教程-答案之书》组件margin左和右等于没偏?
harmonyos·鸿蒙·鸿蒙系统·鸿蒙开发·鸿蒙教程·鸿蒙答案之书·鸿蒙margin
证卡识读张工12 天前
中软高科鸿蒙Next身份证读卡SDK集成说明
华为·harmonyos·鸿蒙·鸿蒙系统
假装自己很用心12 天前
鸿蒙动态路由实现方案
华为·harmonyos·arkts·鸿蒙
半夜偷删你代码14 天前
鸿蒙中选择地区
华为·harmonyos·鸿蒙
雨汨14 天前
鸿蒙-页面和自定义组件生命周期
鸿蒙