zhangzengfei
2020-01-19 20ed84cad4fd237cca40619d0fe7ed39c5e030cd
service/SdkDownLoad.go
@@ -4,63 +4,78 @@
   "bytes"
   "crypto/md5"
   "encoding/hex"
   "encoding/json"
   "fmt"
   "io"
   "io/ioutil"
   "net/http"
   "os"
   "path/filepath"
   "strings"
   "basic.com/valib/logger.git"
   "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) {
func DownSo(url string) (bool, error) {
   resp, err := http.Get(url)
   if err != nil {
      logger.Error("获取文件失败")
      return false,err
      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
      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")
   fileName := GetFileNameFromUrl(url, false)
   md5str, err1 := File2md5("/opt/temp/" + fileName + ".so")
   if err1 != nil {
      logger.Error(err1)
      return false,err1
      return false, err1
   }
   md5str_origin,err2 := ioutil.ReadFile("/opt/temp/"+fileName+".txt")
   md5str_origin, err2 := ioutil.ReadFile("/opt/temp/" + fileName + ".txt")
   if err2 != nil {
      logger.Error("读取解压后的md5文件失败")
      return false,err2
      return false, err2
   }
   flag := CompareMd5([]byte(md5str),md5str_origin)
   flag := CompareMd5([]byte(md5str), md5str_origin)
   if flag {
      logger.Info("两次MD5编码一致!")
   } else {
      logger.Debug("两次MD5编码不一致,请重新下载")
      return false,nil
      return false, nil
   }
   // 从url中截取soName
   soName := GetFileNameFromUrl(url,true)
   soName := GetFileNameFromUrl(url, true)
   f, err := os.Create("/opt/workspace/ruleprocess/algorithm/" + soName)
   if err != nil {
      logger.Error("在项目目录下创建so文件失败")
      return false,err
      return false, err
   }
   data,_ := ioutil.ReadFile("/opt/temp/"+soName)
   _,err4 := f.Write(data)
   data, _ := ioutil.ReadFile("/opt/temp/" + soName)
   _, err4 := f.Write(data)
   if err4 != nil {
      logger.Error("复制文件出错")
      return false,err4
      return false, err4
   }
   return true,nil
   return true, nil
}
func CopyFile(byte []byte, dst string) (w int64, err error) {
@@ -74,7 +89,7 @@
}
// 指定目录的文件生成相应的MD5码文件
func File2md5 (filename string) (string, error) {
func File2md5(filename string) (string, error) {
   // 文件生成MD5加密加密文件
   file, err := os.Open(filename)
   if err != nil {
@@ -88,25 +103,122 @@
      return "", err
   }
   md5Str := hex.EncodeToString(md5.Sum(nil))
   return md5Str,nil
   return md5Str, nil
}
// 从url中截取出文件名,参数是是否带后缀
func GetFileNameFromUrl(url string,withSuffix bool)string {
   fileName := strings.Split(url,"/")[len(strings.Split(url,"/"))-1]
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]
      withoutSuffix := strings.Split(fileName, ".")[0]
      return withoutSuffix
   }
}
// 比较两个MD5编码是否一致
func CompareMd5(value1 []byte,value2 []byte) bool{
   num := bytes.Compare(value1,value2)
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
}