package service
|
|
import (
|
"bytes"
|
"crypto/md5"
|
"encoding/hex"
|
"encoding/json"
|
"fmt"
|
"io"
|
"io/ioutil"
|
"net/http"
|
"os"
|
"path/filepath"
|
"strings"
|
|
"webserver/util"
|
|
"basic.com/dbapi.git"
|
"basic.com/valib/logger.git"
|
)
|
|
func DownSdk(id string) map[string]interface{} {
|
// 下载算法
|
if ok, err := DownSo(id); !ok {
|
logger.Error("下载算法失败", err)
|
return nil
|
}
|
|
return FindLocalSdkSoById(id)
|
}
|
|
// 从服务器上下载文件到临时目录,校验之后如果完整将其拷贝到目标目录下
|
func DownSo(url string) (bool, error) {
|
resp, err := http.Get(url)
|
if err != nil {
|
logger.Error("获取文件失败")
|
return false, err
|
}
|
// 从resp中读出zip文件解压缩,解出face.so,face.txt,然后把解压出的so用MD5编码出一个temp.txt文件,与解压出的so.txt文件比对,
|
body, err := ioutil.ReadAll(resp.Body)
|
if err != nil {
|
logger.Error("读取resp.body失败")
|
return false, err
|
}
|
CopyFile(body, "/opt/temp/temp.zip")
|
util.DeCompress("/opt/temp/temp.zip", "/opt/temp")
|
fileName := GetFileNameFromUrl(url, false)
|
md5str, err1 := File2md5("/opt/temp/" + fileName + ".so")
|
if err1 != nil {
|
logger.Error(err1)
|
return false, err1
|
}
|
md5str_origin, err2 := ioutil.ReadFile("/opt/temp/" + fileName + ".txt")
|
if err2 != nil {
|
logger.Error("读取解压后的md5文件失败")
|
return false, err2
|
}
|
flag := CompareMd5([]byte(md5str), md5str_origin)
|
if flag {
|
logger.Info("两次MD5编码一致!")
|
} else {
|
logger.Debug("两次MD5编码不一致,请重新下载")
|
return false, nil
|
}
|
// 从url中截取soName
|
soName := GetFileNameFromUrl(url, true)
|
f, err := os.Create("/opt/workspace/ruleprocess/algorithm/" + soName)
|
if err != nil {
|
logger.Error("在项目目录下创建so文件失败")
|
return false, err
|
}
|
data, _ := ioutil.ReadFile("/opt/temp/" + soName)
|
_, err4 := f.Write(data)
|
if err4 != nil {
|
logger.Error("复制文件出错")
|
return false, err4
|
}
|
return true, nil
|
}
|
|
func CopyFile(byte []byte, dst string) (w int64, err error) {
|
dstFile, err := os.Create(dst)
|
if err != nil {
|
fmt.Println(err.Error())
|
return
|
}
|
defer dstFile.Close()
|
return io.Copy(dstFile, bytes.NewReader(byte))
|
}
|
|
// 指定目录的文件生成相应的MD5码文件
|
func File2md5(filename string) (string, error) {
|
// 文件生成MD5加密加密文件
|
file, err := os.Open(filename)
|
if err != nil {
|
fmt.Println("os Open error")
|
return "", err
|
}
|
md5 := md5.New()
|
_, err = io.Copy(md5, file)
|
if err != nil {
|
fmt.Println("io copy error")
|
return "", err
|
}
|
md5Str := hex.EncodeToString(md5.Sum(nil))
|
return md5Str, nil
|
}
|
|
// 从url中截取出文件名,参数是是否带后缀
|
func GetFileNameFromUrl(url string, withSuffix bool) string {
|
fileName := strings.Split(url, "/")[len(strings.Split(url, "/"))-1]
|
if withSuffix {
|
return fileName
|
} else {
|
withoutSuffix := strings.Split(fileName, ".")[0]
|
return withoutSuffix
|
}
|
}
|
|
// 比较两个MD5编码是否一致
|
func CompareMd5(value1 []byte, value2 []byte) bool {
|
num := bytes.Compare(value1, value2)
|
if num == 0 {
|
return true
|
} else {
|
return false
|
}
|
}
|
|
func GetSdkList(sdkName string) []map[string]interface{} {
|
// 待返回的数据
|
sdks, idsCache := queryDatabase(sdkName)
|
|
// 查询本地已经存在的算法和远端的全部算法, 然后和已安装的比对, 返回全部可用的算法组. 未安装的算法在前端走下载流程
|
localSdks := GetLocalSdks()
|
for _, sdk := range localSdks {
|
id := sdk["id"].(string)
|
if !idsCache[id] {
|
idsCache[id] = true
|
|
sdk["enable"] = false
|
sdk["installed"] = false
|
|
// 不返回参数信息
|
delete(sdk, "args")
|
sdks = append(sdks, sdk)
|
}
|
|
}
|
|
// 目前还没有远端算法库,
|
// remoteSdks := getRemoteSdks()
|
|
return sdks
|
}
|
|
func queryDatabase(sdkName string) ([]map[string]interface{}, map[string]bool) {
|
var api dbapi.SdkApi
|
ids := make(map[string]bool)
|
sdks := []map[string]interface{}{}
|
|
// 查询已经安装的算法
|
data := api.FindAll(sdkName)
|
for _, sdk := range data {
|
ids[sdk.Id] = true
|
sdks = append(sdks, map[string]interface{}{
|
"id": sdk.Id,
|
"ipc_id": sdk.IpcId,
|
"sdk_type": sdk.SdkType,
|
"sdk_name": sdk.SdkName,
|
"icon": sdk.Icon,
|
"enable": sdk.Enable,
|
"installed": true,
|
})
|
}
|
|
return sdks, ids
|
}
|
|
func GetLocalSdks() []map[string]interface{} {
|
var algos = []map[string]interface{}{}
|
|
AlgorithmFiles := "/opt/vasystem/bin/algorithm/*.json"
|
|
files, err := filepath.Glob(AlgorithmFiles)
|
if err != nil {
|
fmt.Println("Cannot access algorithm json files: No such file or directory")
|
return algos
|
}
|
|
for _, filename := range files {
|
algo := make(map[string]interface{})
|
f, err := ioutil.ReadFile(filename)
|
if err != nil {
|
return algos
|
}
|
|
if err := json.Unmarshal(f, &algo); err != nil {
|
return algos
|
}
|
|
algos = append(algos, map[string]interface{}{
|
"id": algo["sdkId"],
|
"ipc_id": algo["ipcId"],
|
"sdk_type": algo["sdkType"],
|
"sdk_name": algo["sdkName"],
|
"icon": algo["icon"],
|
"args": algo["sdkArgs"],
|
})
|
}
|
|
return algos
|
}
|
|
func FindLocalSdkSoById(id string) map[string]interface{} {
|
localAlgos := GetLocalSdks()
|
for _, sdk := range localAlgos {
|
if sdk["id"].(string) == id {
|
return sdk
|
}
|
}
|
|
return nil
|
}
|