package service
|
|
import (
|
"basic.com/valib/logger.git"
|
"errors"
|
"fmt"
|
"io"
|
"net/http"
|
"os"
|
"path"
|
"strconv"
|
"strings"
|
"sync"
|
"vamicro/extend/util"
|
)
|
|
//正在安装列表
|
var insIngMap sync.Map
|
|
//判断是否在安装中
|
func IsInstalling(id string) bool {
|
_, ok := insIngMap.Load(id)
|
return ok
|
}
|
|
//安装进度
|
type InsProgress struct {
|
Status string `json:"status"`
|
Progress int `json:"progress"`
|
Size uint64 `json:"size"`
|
IsDone bool `json:"isDone"` //不管成功或者失败,标志本次安装已完成
|
}
|
|
const (
|
InsStatus_Downloading = "下载中..."
|
InsStatus_Err = "安装包下载失败"
|
InsStatus_UnPackErr = "安装包解压失败"
|
InsStatus_PackageChecking = "安装包校验中..."
|
InsStatus_CheckErr = "安装包校验失败"
|
InsStatus_Installing = "安装中..."
|
InsStatus_InstallErr = "安装失败"
|
InsStatus_Done = "已安装"
|
)
|
|
type WriteCounter struct {
|
Total uint64
|
|
iPgs *InsProgress
|
}
|
|
func (wc *WriteCounter) PrintProgress() {
|
logger.Info(strings.Repeat(" ", 35))
|
//logger.Info("Downloading... ",humanize.Bytes(wc.Total)," complete")
|
|
percent := (wc.Total * 100) / wc.iPgs.Size
|
|
wc.iPgs.Progress = int(percent)
|
}
|
|
func (wc *WriteCounter) Write(p []byte) (int, error) {
|
n := len(p)
|
wc.Total += uint64(n)
|
wc.PrintProgress()
|
return n, nil
|
}
|
|
//下载文件
|
func DownloadFile(fPath string, url string, iProgress *InsProgress) error {
|
f, err := os.Create(fPath)
|
if err != nil {
|
return err
|
}
|
resp, err := http.Get(url)
|
if err != nil {
|
f.Close()
|
return err
|
}
|
defer resp.Body.Close()
|
counter := &WriteCounter{
|
iPgs: iProgress,
|
}
|
if _, err = io.Copy(f, io.TeeReader(resp.Body, counter)); err != nil {
|
f.Close()
|
return err
|
}
|
fmt.Printf("\n")
|
f.Close()
|
//if err = os.Rename(fPath, fPath);err != nil {
|
// return err
|
//}
|
return nil
|
}
|
|
type downPara struct {
|
URL string //待下载文件的url
|
FileName string //待下载文件的名称
|
}
|
|
//procPath 下载到目的文件夹
|
func downloadExtraFile(downloadDir string, extra downPara, fb func(length, downLen int64)) error {
|
if extra.URL == "" {
|
return nil
|
}
|
|
var (
|
fsize int64
|
buf = make([]byte, 32*1024)
|
written int64
|
)
|
|
// 创建应用下载目录, 后续会直接剪切到编译环境
|
//downloadDir := path.Join(procPath, "pre-install-sdks")
|
//err := dirPing(downloadDir)
|
//if err != nil {
|
// logger.Warn("pack error: can not create dir.", err)
|
// return errors.New("can not create dir")
|
//}
|
|
downloadPath := path.Join(downloadDir, extra.FileName)
|
tmpFilePath := downloadPath + ".download"
|
logger.Debug(tmpFilePath)
|
//创建一个http client
|
client := new(http.Client)
|
//client.Timeout = time.Second * 60 //设置超时时间
|
//get方法获取资源
|
resp, err := client.Get(extra.URL)
|
if err != nil {
|
logger.Error("client.Get err:", err)
|
return err
|
}
|
|
//读取服务器返回的文件大小
|
fsize, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 32)
|
if err != nil {
|
logger.Error("读取服务器返回文件大小err: ", err)
|
}
|
|
if isFileExist(downloadPath, fsize) {
|
return err
|
}
|
|
logger.Debug("fsize", fsize)
|
//创建文件
|
file, err := os.Create(tmpFilePath)
|
if err != nil {
|
logger.Error("os.Create err: ", err)
|
return err
|
}
|
defer file.Close()
|
if resp.Body == nil {
|
return errors.New("body is null")
|
}
|
defer resp.Body.Close()
|
//下面是 io.copyBuffer() 的简化版本
|
for {
|
//读取bytes
|
nr, er := resp.Body.Read(buf)
|
if nr > 0 {
|
//写入bytes
|
nw, ew := file.Write(buf[0:nr])
|
//数据长度大于0
|
if nw > 0 {
|
written += int64(nw)
|
}
|
//写入出错
|
if ew != nil {
|
err = ew
|
break
|
}
|
//读取是数据长度不等于写入的数据长度
|
if nr != nw {
|
err = io.ErrShortWrite
|
break
|
}
|
}
|
if er != nil {
|
if er != io.EOF {
|
err = er
|
}
|
break
|
}
|
//没有错误了快使用 callback
|
if fb != nil {
|
fb(fsize, written)
|
}
|
}
|
logger.Debug(err)
|
if err == nil {
|
file.Close()
|
err = os.Rename(tmpFilePath, downloadPath)
|
logger.Debug(err)
|
}
|
return err
|
}
|
|
// 如果文件夹不存在就会创建
|
func dirPing(path string) error {
|
if !util.DirExists(path) {
|
e := os.MkdirAll(path, 00777)
|
if e != nil {
|
return e
|
}
|
}
|
return nil
|
}
|
|
func isFileExist(filename string, filesize int64) bool {
|
info, err := os.Stat(filename)
|
if os.IsNotExist(err) {
|
logger.Debug(info)
|
return false
|
}
|
if filesize == info.Size() {
|
logger.Debug("安装包已存在!", info.Name(), info.Size(), info.ModTime())
|
return true
|
}
|
del := os.Remove(filename)
|
if del != nil {
|
logger.Error(del)
|
}
|
return false
|
}
|