最近在使用华为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()