package main import ( "encoding/json" "fmt" "io" "io/ioutil" "log" "net/http" "os" "strings" "sync" "time" "github.com/kardianos/osext" ) // 配置文件 type configuration struct { Proxy string } var G_config configuration func readConfig() { folderPath, err := osext.ExecutableFolder() if err != nil { log.Fatal(err) } // 打开文件 file, err := os.Open(folderPath + "/config.json") if err != nil { return } // 关闭文件 defer file.Close() //NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。 decoder := json.NewDecoder(file) G_config = configuration{} //Decode从输入流读取下一个json编码值并保存在v指向的值里 err = decoder.Decode(&G_config) if err != nil { fmt.Println("Error:", err) } // fmt.Println("proxy:" + G_config.Proxy) } // 下载 type people struct { Tag_name string `json:"tag_name"` //Tag_name 小写变成私有 } func api_get_version(project string) string { git_api := "https://api.github.com/repos/" + project + "/releases/latest" // 目标URL url := git_api // 发送HTTP GET请求 resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close() // 读取响应体 body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } // 解析JSON数据 responseData := people{} if err := json.Unmarshal(body, &responseData); err != nil { panic(err) } // 打印解析后的数据 // fmt.Println("tag_name:" + responseData.Tag_name) // latest_version = responseData.tag_name return responseData.Tag_name } type Downloader struct { io.Reader Total int64 Current int64 } func printProgressBar(progress int64, total int64) { // bar := "" // numSlashes := progress * 100 / total / 5 // for i := 0; i < numSlashes; i++ { // bar += "\u2588" // 这是一个完整的块字符 // } // fmt.Printf("下载进度: [%-21s] %.2f%%\r", bar, float64(progress*100.0/total)) fmt.Printf(" 正在下载:%d / %d bytes (%.2f%%)\r", progress, total, float32(progress*10000/total)/100) } func (d *Downloader) Read(p []byte) (n int, err error) { n, err = d.Reader.Read(p) d.Current += int64(n) printProgressBar(d.Current, d.Total) return } func downloadFile(item int, url string, filePath string) { defer wg.Done() fmt.Printf("%d.下载%s\n", item, filePath) resp, err := http.Get(url) if err != nil { log.Fatalln(err) } defer func() { _ = resp.Body.Close() }() file, err := os.Create(filePath) if err != nil { fmt.Println("文件创建失败:", err) // 其他处理 } defer func() { _ = file.Close() }() downloader := &Downloader{ Reader: resp.Body, Total: resp.ContentLength, } if _, err := io.Copy(file, downloader); err != nil { log.Fatalln(err) } fmt.Println() // 新的一行以清除进度条打印 } var wg sync.WaitGroup func http_down(project string, down_list string, proxy string) { // fmt.Println(project, down_list, proxy) // 获取最新版本 latest_version := api_get_version(project) // 创建文件夹 folderPath := latest_version err := os.MkdirAll(folderPath, os.ModePerm) if err != nil { fmt.Printf("创建文件夹错误: %v\n", err) return } // 分割下载列表 git_down_url := proxy + project + "/releases/download/" + latest_version + "/" parts := strings.Split(down_list, ",") task := make(map[string]string) for i := 0; i < len(parts); i++ { // 替换 version_str := strings.ReplaceAll(latest_version, "v", "") version_str = strings.ReplaceAll(version_str, "V", "") filename := strings.ReplaceAll(parts[i], "[version]", version_str) // 存入 task[git_down_url+filename] = folderPath + "/" + filename } item := 1 for k, v := range task { wg.Add(1) downloadFile(item, k, v) item += 1 } wg.Wait() fmt.Println("下载完成") time.Sleep(1 * time.Second) } func main() { // parser := argparse.NewParser("GitAutoupdater", "这是git最新版本的更新工具") // name := parser.String("n", "name", &argparse.Options{Required: false, Help: "项目,譬如 fatedier/frp", Default: "fatedier/frp"}) // list := parser.String("l", "list", &argparse.Options{Required: false, Help: "下载列表(1.[version]可替换最新版本 2.用,分割多个文件),譬如 frp_[version]_windows_amd64.zip", Default: "frp_[version]_windows_amd64.zip"}) // proxy := parser.String("p", "proxy", &argparse.Options{Required: false, Help: "代理,譬如 https://ghproxy.com/https://github.com/", Default: "https://github.com/"}) // err := parser.Parse(os.Args) // if err != nil { // fmt.Print(parser.Usage(err)) // 帮助 -h or --help // return // } name := "" list := "" proxy := "https://github.com/" for i, num := range os.Args[1:] { switch i { case 0: name = num case 1: list = num case 2: proxy = num default: fmt.Println(`未知参数:`, num) } } // 优先级:命令>配置>默认 readConfig() if proxy == "https://github.com/" && G_config.Proxy != "" { proxy = G_config.Proxy } fmt.Println("proxy:", proxy) http_down(name, list, proxy) }