最近在使用華為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));// 構建請求體bodylet 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()