daShangDao_kfzgw-info/main.go
2026-02-27 11:46:40 +08:00

1715 lines
53 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
//import (
// "bufio"
// "context"
// "encoding/json"
// "fmt"
// "gopkg.in/yaml.v3"
// "io"
// "io/ioutil"
// "net"
// "net/http"
// "os"
// "os/exec"
// "path/filepath"
// "strings"
// "syscall"
// "time"
// "unsafe"
//)
//
//// 颜色代码常量
//const (
// ColorReset = "\033[0m"
// ColorRed = "\033[31m"
// ColorGreen = "\033[32m"
// ColorYellow = "\033[33m"
// ColorBlue = "\033[34m"
// ColorMagenta = "\033[35m"
// ColorCyan = "\033[36m"
// ColorWhite = "\033[37m"
// ColorGray = "\033[90m"
//
// // 加粗
// ColorBoldRed = "\033[1;31m"
// ColorBoldGreen = "\033[1;32m"
// ColorBoldYellow = "\033[1;33m"
// ColorBoldBlue = "\033[1;34m"
//
// // 背景色
// ColorBgRed = "\033[41m"
// ColorBgGreen = "\033[42m"
//)
//
//// 定义结构体来映射 YAML 数据
//type VersionConfig struct {
// CsvVersion string `json:"csv"`
// KongfzVersion string `json:"kongfz"`
// LoggerVersion string `json:"logger"`
// ModuleErpVersion string `json:"module-erp"`
// ModuleKongfzVersion string `json:"module-kongfz"`
// ModuleTaskPoolVersion string `json:"module-taskPool"`
// ModuleVerifyPriceVersion string `json:"module-verifyPrice"`
// ModuleCenterBookVersion string `json:"module-centerBook"`
// ModuleLoginVersion string `json:"module-login"`
// PicToolVersion string `json:"picTool"`
// ProxyVersion string `json:"proxy"`
//}
//
//type VerifyPriceYAML struct {
// VerifyPriceLatestVersion string `yaml:"verifyPriceLatestVersion"`
//}
//
//// 自定义日志函数,添加颜色
//func printInfo(format string, v ...interface{}) {
// fmt.Printf(ColorCyan+"[信息] "+format+ColorReset+"\n", v...)
//}
//
//func printSuccess(format string, v ...interface{}) {
// fmt.Printf(ColorGreen+"[成功] "+format+ColorReset+"\n", v...)
//}
//
//func printWarning(format string, v ...interface{}) {
// fmt.Printf(ColorYellow+"[警告] "+format+ColorReset+"\n", v...)
//}
//
//func printError(format string, v ...interface{}) {
// fmt.Printf(ColorRed+"[错误] "+format+ColorReset+"\n", v...)
//}
//
//func printDebug(format string, v ...interface{}) {
// fmt.Printf(ColorGray+"[调试] "+format+ColorReset+"\n", v...)
//}
//
//func printBanner(format string, v ...interface{}) {
// fmt.Printf(ColorBoldBlue+"== "+format+" ==\n"+ColorReset, v...)
//}
//
//func printDownload(format string, v ...interface{}) {
// fmt.Printf(ColorBoldGreen+"[下载] "+format+ColorReset+"\n", v...)
//}
//
//func printVersionInfo(label, version string) {
// fmt.Printf(ColorBoldYellow+"%-30s: "+ColorCyan+"%s"+ColorReset+"\n", label, version)
//}
//
//func main() {
// // 打印彩色横幅
// fmt.Printf(ColorBoldBlue + "================================================\n")
// fmt.Printf(" 核价软件更新器\n")
// fmt.Printf("================================================\n" + ColorReset)
// printWarning("更新时请勿操作!!!")
// // 获取当前工作目录
// currentDir, err := os.Getwd()
// if err != nil {
// printError("获取当前目录失败: %v", err)
// }
// printInfo("当前目录: %v", currentDir)
//
// // 获取选品中心中verify_price_version_test.json
// printInfo("正在检查核价软件版本...")
// verifyPriceVersionJSON, err := getVerifyPriceVersionJSON()
// if err != nil {
// printError("读取核价软件版本信息失败: %v", err)
// }
//
// // 直接读取yaml文件
// yamlPath := filepath.Join(currentDir, "version.yaml")
// // 读取 YAML 文件
// data, err := ioutil.ReadFile(yamlPath)
// if err != nil {
// printError("读取YAML配置文件失败: %v", err)
// }
//
// // 解析 YAML
// var config VerifyPriceYAML
// err = yaml.Unmarshal(data, &config)
// if err != nil {
// printError("解析 YAML 配置失败: %v", err)
// }
// printVersionInfo("当前核价软件版本号", config.VerifyPriceLatestVersion)
//
// // 检查并下载核价软件主程序
// printInfo("检查核价软件主程序...")
// if _, err := os.Stat(filepath.Join(currentDir, "VerifyPriceApp.exe")); os.IsNotExist(err) {
// printDownload("发现核价软件缺失,开始下载...")
// url := fmt.Sprintf("https://newverifyprice.buzhiyushu.cn/exe/VerifyPriceApp_%s.exe", verifyPriceVersionJSON.VerifyPriceLatestVersion)
// err = downloadEXE(url, currentDir, "VerifyPriceApp.exe")
// if err != nil {
// if err.Error() == "The process cannot access the file because it is being used by another process." {
// printWarning("文件被占用,请重新启动与书同行.exe软件")
// } else {
// printError("下载核价软件失败: %v", err)
// }
// } else {
// printSuccess("核价软件下载完成")
// }
// //修改yaml文件
// config.VerifyPriceLatestVersion = verifyPriceVersionJSON.VerifyPriceLatestVersion
// err = writeYAML(yamlPath, config)
// if err != nil {
// printError("更新YAML配置文件失败: %v", err)
// }
// } else {
// if verifyPriceVersionJSON.VerifyPriceLatestVersion != config.VerifyPriceLatestVersion || config.VerifyPriceLatestVersion == "" {
// printDownload("发现新版本核价软件,开始更新...")
// url := fmt.Sprintf("https://newverifyprice.buzhiyushu.cn/exe/VerifyPriceApp_%s.exe", verifyPriceVersionJSON.VerifyPriceLatestVersion)
// err = downloadEXE(url, currentDir, "VerifyPriceApp.exe")
// if err != nil {
// if err.Error() == "The process cannot access the file because it is being used by another process." {
// printWarning("文件被占用,请重新启动与书同行.exe软件")
// } else {
// printError("下载核价软件失败: %v", err)
// }
// } else {
// printSuccess("核价软件更新完成")
// }
// //修改yaml文件
// config.VerifyPriceLatestVersion = verifyPriceVersionJSON.VerifyPriceLatestVersion
// err = writeYAML(yamlPath, config)
// if err != nil {
// printError("更新YAML配置文件失败: %v", err)
// }
// } else {
// printSuccess("核价软件已是最新版本")
// }
// }
//
// // 获取ES2中version.json
// printInfo("正在检查DLL组件版本...")
// versionsJSON, err := getVersionsJSON()
// if err != nil {
// printError("读取DLL版本信息失败: %v", err)
// }
//
// // 打印版本信息标题
// printBanner("版本信息")
//
// // 打印所有版本信息
// printVersionInfo("最新核价软件版本", verifyPriceVersionJSON.VerifyPriceLatestVersion)
// printVersionInfo("csv.dll版本号:", versionsJSON.CsvVersion)
// printVersionInfo("kongfz.dll版本号:", versionsJSON.KongfzVersion)
// printVersionInfo("logger.dll版本号:", versionsJSON.LoggerVersion)
// printVersionInfo("module-centerBook.dll版本号:", versionsJSON.ModuleCenterBookVersion)
// printVersionInfo("module-login.dll版本号:", versionsJSON.ModuleLoginVersion)
// printVersionInfo("module-erp.dll版本号:", versionsJSON.ModuleErpVersion)
// printVersionInfo("module-kongfz.dll版本号:", versionsJSON.ModuleKongfzVersion)
// printVersionInfo("module-taskPool.dll版本号:", versionsJSON.ModuleTaskPoolVersion)
// printVersionInfo("module-verifyPrice.dll版本号:", versionsJSON.ModuleVerifyPriceVersion)
// printVersionInfo("picTool.dll版本号:", versionsJSON.PicToolVersion)
// printVersionInfo("proxy.dll版本号:", versionsJSON.ProxyVersion)
//
// // 验证并更新DLL文件
// printBanner("组件检查与更新")
//
// // 验证csv.dll文件版本
// printInfo("检查csv.dll...")
// csvVersion, err := csvDllVersion(currentDir)
// if err != nil {
// printWarning("获取csv.dll版本失败: %v", err)
// }
// if versionsJSON.CsvVersion != csvVersion && csvVersion != "" {
// printDownload("csv.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "csv.dll"), "csv.dll", "")
// if err != nil {
// printError("下载csv.dll失败: %v", err)
// } else {
// printSuccess("csv.dll更新完成")
// }
// } else {
// printSuccess("csv.dll已是最新版本")
// }
//
// // 验证kongfz.dll文件版本
// printInfo("检查kongfz.dll...")
// kongfzVersion, err := kongfzDllVersion(currentDir)
// if err != nil {
// printWarning("获取kongfz.dll版本失败: %v", err)
// }
// if versionsJSON.KongfzVersion != kongfzVersion && kongfzVersion != "" {
// printDownload("kongfz.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "kongfz.dll"), "kongfz.dll", "")
// if err != nil {
// printError("下载kongfz.dll失败: %v", err)
// } else {
// printSuccess("kongfz.dll更新完成")
// }
// } else {
// printSuccess("kongfz.dll已是最新版本")
// }
//
// // 验证logger.dll文件版本
// printInfo("检查logger.dll...")
// loggerVersion, err := loggerDllVersion(currentDir)
// if err != nil {
// printWarning("获取logger.dll版本失败: %v", err)
// }
// if versionsJSON.LoggerVersion != loggerVersion && loggerVersion != "" {
// printDownload("logger.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "logger.dll"), "logger.dll", "")
// if err != nil {
// printError("下载logger.dll失败: %v", err)
// } else {
// printSuccess("logger.dll更新完成")
// }
// } else {
// printSuccess("logger.dll已是最新版本")
// }
//
// // 验证module-centerBook.dll文件版本
// printInfo("检查module-centerBook.dll...")
// moduleCenterBookVersion, err := moduleCenterBookDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-centerBook.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleCenterBookVersion != moduleCenterBookVersion && moduleCenterBookVersion != "" {
// printDownload("module-centerBook.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-centerBook.dll"), "module-centerBook.dll", "")
// if err != nil {
// printError("下载module-centerBook.dll失败: %v", err)
// } else {
// printSuccess("module-centerBook.dll更新完成")
// }
// } else {
// printSuccess("module-centerBook.dll已是最新版本")
// }
//
// // 验证module-login.dll文件版本
// printInfo("检查module-login.dll...")
// moduleLoginVersion, err := moduleLoginDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-login.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleLoginVersion != moduleLoginVersion && moduleLoginVersion != "" {
// printDownload("module-login.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-login.dll"), "module-login.dll", "")
// if err != nil {
// printError("下载module-login.dll失败: %v", err)
// } else {
// printSuccess("module-login.dll更新完成")
// }
// } else {
// printSuccess("module-login.dll已是最新版本")
// }
//
// // 验证module-erp.dll文件版本
// printInfo("检查module-erp.dll...")
// moduleErpVersion, err := moduleErpDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-erp.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleErpVersion != moduleErpVersion && moduleErpVersion != "" {
// printDownload("module-erp.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-erp.dll"), "module-erp.dll", "")
// if err != nil {
// printError("下载module-erp.dll失败: %v", err)
// } else {
// printSuccess("module-erp.dll更新完成")
// }
// } else {
// printSuccess("module-erp.dll已是最新版本")
// }
//
// // 验证module-kongfz.dll文件版本
// printInfo("检查module-kongfz.dll...")
// moduleKongfzVersion, err := moduleKongfzDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-kongfz.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleKongfzVersion != moduleKongfzVersion && moduleKongfzVersion != "" {
// printDownload("module-kongfz.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-kongfz.dll"), "module-kongfz.dll", "")
// if err != nil {
// printError("下载module-kongfz.dll失败: %v", err)
// } else {
// printSuccess("module-kongfz.dll更新完成")
// }
// } else {
// printSuccess("module-kongfz.dll已是最新版本")
// }
//
// // 验证module-taskPool.dll文件版本
// printInfo("检查module-taskPool.dll...")
// moduleTaskPoolVersion, err := moduleTaskPoolDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-taskPool.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleTaskPoolVersion != moduleTaskPoolVersion && moduleTaskPoolVersion != "" {
// printDownload("module-taskPool.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-taskPool.dll"), "module-taskPool.dll", "")
// if err != nil {
// printError("下载module-taskPool.dll失败: %v", err)
// } else {
// printSuccess("module-taskPool.dll更新完成")
// }
// } else {
// printSuccess("module-taskPool.dll已是最新版本")
// }
//
// // 验证module-verifyPrice.dll文件版本
// printInfo("检查module-verifyPrice.dll...")
// moduleVerifyPriceVersion, err := moduleVerifyPriceDllVersion(currentDir)
// if err != nil {
// printWarning("获取module-verifyPrice.dll版本失败: %v", err)
// }
// if versionsJSON.ModuleVerifyPriceVersion != moduleVerifyPriceVersion && moduleVerifyPriceVersion != "" {
// printDownload("module-verifyPrice.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-verifyPrice.dll"), "module-verifyPrice.dll", "")
// if err != nil {
// printError("下载module-verifyPrice.dll失败: %v", err)
// } else {
// printSuccess("module-verifyPrice.dll更新完成")
// }
// } else {
// printSuccess("module-verifyPrice.dll已是最新版本")
// }
//
// // 验证picTool.dll文件版本
// printInfo("检查picTool.dll...")
// picToolVersion, err := picToolDllVersion(currentDir)
// if err != nil {
// printWarning("获取picTool.dll版本失败: %v", err)
// }
// if versionsJSON.PicToolVersion != picToolVersion && picToolVersion != "" {
// printDownload("picTool.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "picTool.dll"), "picTool.dll", "")
// if err != nil {
// printError("下载picTool.dll失败: %v", err)
// } else {
// printSuccess("picTool.dll更新完成")
// }
// } else {
// printSuccess("picTool.dll已是最新版本")
// }
//
// // 验证proxy.dll文件版本
// printInfo("检查proxy.dll...")
// proxyVersion, err := proxyDllVersion(currentDir)
// if err != nil {
// printWarning("获取proxy.dll版本失败: %v", err)
// }
// if versionsJSON.ProxyVersion != proxyVersion && proxyVersion != "" {
// printDownload("proxy.dll需要更新")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "proxy.dll"), "proxy.dll", "")
// if err != nil {
// printError("下载proxy.dll失败: %v", err)
// } else {
// printSuccess("proxy.dll更新完成")
// }
// } else {
// printSuccess("proxy.dll已是最新版本")
// }
//
// printWarning("更新时请勿操作!!!出现:立即按回车键打开核价软件,可以点击 回车键")
//
// // 启动提示
// printBanner("启动核价软件")
// fmt.Printf("\n" + ColorBoldGreen + "立即按回车键打开核价软件..." + ColorReset)
// fmt.Printf(ColorGray + "(或30秒后自动打开)\n" + ColorReset)
//
// // 创建带超时的输入读取器
// inputCh := make(chan bool, 1)
//
// // 启动一个goroutine等待用户输入
// go func() {
// bufio.NewReader(os.Stdin).ReadBytes('\n')
// inputCh <- true
// }()
// // 设置30秒超时
// timeout := 30 * time.Second
//
// select {
// case <-inputCh:
// printSuccess("用户按下了回车键,立即打开核价软件")
// case <-time.After(timeout):
// printWarning("等待超时30秒自动打开核价软件")
// }
//
// // 尝试打开 VerifyPriceApp.exe
// verifyPriceAppPath := filepath.Join(currentDir, "VerifyPriceApp.exe")
// printInfo("正在启动核价软件: %s", verifyPriceAppPath)
//
// // 检查文件是否存在 --- TODO 存在问题,有可能打不开 VerifyPriceApp.exe
// if _, err := os.Stat(verifyPriceAppPath); os.IsNotExist(err) {
// printError("核价软件主程序不存在: %s", verifyPriceAppPath)
// } else {
// // 启动 VerifyPriceApp.exe
// cmd := exec.Command(verifyPriceAppPath)
//
// // 设置工作目录为当前目录
// cmd.Dir = currentDir
//
// // 启动进程(不等待它完成)
// err := cmd.Start()
// if err != nil {
// printError("启动核价软件失败: %v", err)
// } else {
// printSuccess("核价软件已启动 (PID: %d)", cmd.Process.Pid)
//
// // 给新进程一点时间启动(可选)
// time.Sleep(100 * time.Millisecond)
// }
// }
//
// printBanner("程序执行完毕")
//}
//
//// 将结构体写回YAML文件
//func writeYAML(filePath string, config VerifyPriceYAML) error {
// // 将结构体序列化为YAML
// yamlData, err := yaml.Marshal(config)
// if err != nil {
// return fmt.Errorf("序列化YAML失败: %v", err)
// }
//
// // 创建备份文件(可选)
// backupFilePath := filePath + ".bak"
// err = backupFile(filePath, backupFilePath)
// if err != nil {
// printDebug("创建备份文件失败: %v", err)
// }
//
// // 写回文件
// err = ioutil.WriteFile(filePath, yamlData, 0755)
// if err != nil {
// return fmt.Errorf("写入文件失败: %v", err)
// }
//
// return nil
//}
//
//// 备份原文件
//func backupFile(originalPath, backupPath string) error {
// // 读取原文件
// data, err := ioutil.ReadFile(originalPath)
// if err != nil {
// return err
// }
//
// // 写入备份文件
// return ioutil.WriteFile(backupPath, data, 0755)
//}
//
//func downloadEXE(url, folderPath, filename string) error {
// // 确保文件夹存在
// if err := os.MkdirAll(folderPath, 0755); err != nil {
// return fmt.Errorf("创建文件夹失败: %v", err)
// }
//
// // 拼接完整文件路径
// filePath := filepath.Join(folderPath, filename)
//
// printDebug("下载到: %s", filePath)
//
// // 发送HTTP请求
// resp, err := http.Get(url)
// if err != nil {
// return fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
//
// // 检查响应状态
// if resp.StatusCode != http.StatusOK {
// return fmt.Errorf("下载失败,状态码: %d", resp.StatusCode)
// }
//
// // 创建文件
// file, err := os.Create(filePath)
// if err != nil {
// return fmt.Errorf("创建文件失败: %v", err)
// }
// defer file.Close()
//
// // 下载文件
// _, err = io.Copy(file, resp.Body)
// if err != nil {
// return fmt.Errorf("写入文件失败: %v", err)
// }
//
// return nil
//}
//
//// VersionInfo 定义 JSON 结构体
//type VersionInfo struct {
// LatestVersion string `json:"latestVersion"`
// HistoricalVersions []string `json:"historicalVersions"`
// VerifyPriceLatestVersion string `json:"verifyPriceLatestVersion"`
//}
//
//// 读取选品中心中verify_price_version_test.json文件
//func getVerifyPriceVersionJSON() (*VersionInfo, error) {
// // 目标 URL
// url := "https://newverifyprice.buzhiyushu.cn/verify_price_version.json"
//
// // 创建 HTTP 客户端,设置超时时间
// client := &http.Client{
// Timeout: 30 * time.Second,
// }
//
// // 发送 GET 请求
// resp, err := client.Get(url)
// if err != nil {
// return nil, fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
//
// // 检查响应状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP 请求失败,状态码: %d", resp.StatusCode)
// }
//
// // 读取响应体
// body, err := io.ReadAll(resp.Body)
// if err != nil {
// return nil, fmt.Errorf("读取响应失败: %v", err)
// }
//
// // 解析 JSON 数据
// var versionInfo VersionInfo
// err = json.Unmarshal(body, &versionInfo)
// if err != nil {
// return nil, fmt.Errorf("解析 JSON 失败: %v", err)
// }
// return &versionInfo, nil
//}
//
//// 读取ES2中versions.json文件
//func getVersionsJSON() (*VersionConfig, error) {
// // 目标 URL
// url := "http://36.212.20.113:53300/version.json"
//
// // 创建 HTTP 客户端,设置超时时间
// client := &http.Client{
// Timeout: 30 * time.Second,
// }
//
// // 发送 GET 请求
// resp, err := client.Get(url)
// if err != nil {
// return nil, fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
//
// // 检查响应状态码
// if resp.StatusCode != http.StatusOK {
// return nil, fmt.Errorf("HTTP 请求失败,状态码: %d", resp.StatusCode)
// }
//
// // 读取响应体
// body, err := io.ReadAll(resp.Body)
// if err != nil {
// return nil, fmt.Errorf("读取响应失败: %v", err)
// }
//
// // 解析 JSON 数据
// var versionConfig VersionConfig
// err = json.Unmarshal(body, &versionConfig)
// if err != nil {
// return nil, fmt.Errorf("解析 JSON 失败: %v", err)
// }
// return &versionConfig, nil
//}
//
//// cStr 将 C 字符串指针转换为 Go 字符串
//func cStr(ptr uintptr) string {
// if ptr == 0 {
// return ""
// }
// var b []byte
// for {
// c := *(*byte)(unsafe.Pointer(ptr))
// if c == 0 {
// break
// }
// b = append(b, c)
// ptr++
// }
// return string(b)
//}
//
//// 查询csv.dll版本号
//func csvDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "csv.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("csv.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "csv.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 csv.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载csv.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找csv.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用csv.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询kongfz.dll版本号
//func kongfzDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "kongfz.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("kongfz.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "kongfz.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 kongfz.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载kongfz.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找kongfz.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用kongfz.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询logger.dll版本号
//func loggerDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "logger.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("logger.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "logger.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 logger.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载logger.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找logger.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用logger.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module_centerBook.dll版本号
//func moduleCenterBookDllVersion(currentDir string) (string, error) {
// // 方案1使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-centerBook.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-centerBook.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-centerBook.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-centerBook.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-centerBook.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-centerBook.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-centerBook.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module_login.dll版本号
//func moduleLoginDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-login.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-login.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-login.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-login.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-login.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-login.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-login.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
//
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module-erp.dll版本号
//func moduleErpDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-erp.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-erp.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-erp.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-erp.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-erp.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-erp.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-erp.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
//
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module-kongfz.dll版本号
//func moduleKongfzDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-kongfz.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-kongfz.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-kongfz.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-kongfz.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-kongfz.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-kongfz.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-kongfz.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module-taskPool.dll版本号
//func moduleTaskPoolDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-taskPool.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-taskPool.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-taskPool.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-taskPool.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-taskPool.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-taskPool.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-taskPool.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询module-verifyPrice.dll版本号
//func moduleVerifyPriceDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "module-verifyPrice.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("module-verifyPrice.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-verifyPrice.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 module-verifyPrice.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载module-verifyPrice.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion"
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找module-verifyPrice.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用module-verifyPrice.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询picTool.dll版本号
//func picToolDllVersion(currentDir string) (string, error) {
// // 使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "picTool.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("picTool.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "picTool.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 picTool.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载picTool.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion" // 你的函数名
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找picTool.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用picTool.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
//// 查询proxy.dll版本号
//func proxyDllVersion(currentDir string) (string, error) {
// // 方案1使用绝对路径
// dllPath := filepath.Join(currentDir, "dll", "proxy.dll")
//
// // 判断dll文件是否存在不存在下载新版本
// _, err := os.Stat(dllPath)
// if err != nil {
// if os.IsNotExist(err) {
// printDownload("proxy.dll文件缺失开始下载...")
// err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "proxy.dll", "")
// if err != nil {
// return "", fmt.Errorf("下载 proxy.dll 文件失败: %v", err)
// }
// return "", nil
// }
// }
//
// // 加载DLL
// dll, err := syscall.LoadDLL(dllPath)
// if err != nil {
// return "", fmt.Errorf("加载proxy.dll文件失败: %v", err)
// }
//
// // 查找函数
// funcName := "GetVersion" // 你的函数名
// proc, err := dll.FindProc(funcName)
// if err != nil {
// return "", fmt.Errorf("查找proxy.dll GetVersion 函数失败: %v", err)
// }
//
// // 调用函数(无参数版本)
// ret, _, err := proc.Call()
// if err != nil && err.Error() != "The operation completed successfully." {
// return "", fmt.Errorf("调用proxy.dll GetVersion 函数失败: %v", err)
// }
// str := cStr(ret)
// // 释放C字符串
// if proc, err = dll.FindProc("FreeCString"); err == nil {
// defer proc.Call(ret)
// }
// return str, nil
//}
//
////func downloadDLL(url, outputPath, filename, version string) error {
//// // 1. 确保目录存在
//// dir := filepath.Dir(outputPath)
//// if err := os.MkdirAll(dir, 0755); err != nil {
//// return fmt.Errorf("创建目录失败: %v", err)
//// }
////
//// // 2. 创建临时文件路径(避免直接操作目标文件)
//// tempPath := outputPath + ".tmp"
////
//// // 清理可能存在的旧临时文件
//// if _, err := os.Stat(tempPath); err == nil {
//// os.Remove(tempPath)
//// }
////
//// // 3. 检查目标文件是否存在
//// if _, err := os.Stat(outputPath); err == nil {
//// // 尝试重命名原文件(而不是直接删除)
//// backupPath := outputPath + ".bak"
//// if err := os.Rename(outputPath, backupPath); err != nil {
//// // 重命名失败,尝试直接删除
//// for i := 0; i < 3; i++ { // 重试3次
//// if err := os.Remove(outputPath); err == nil {
//// break
//// }
//// if i == 2 { // 最后一次尝试
//// if strings.Contains(err.Error(), "Access is denied") {
//// return fmt.Errorf("文件被其他程序占用,请关闭可能使用此文件的程序后再试: %s", outputPath)
//// }
//// return fmt.Errorf("无法删除已存在的文件: %v", err)
//// }
//// time.Sleep(1 * time.Second)
//// }
//// } else {
//// // 异步清理备份文件
//// go func() {
//// time.Sleep(30 * time.Second) // 30秒后清理
//// if _, err := os.Stat(backupPath); err == nil {
//// os.Remove(backupPath)
//// }
//// }()
//// }
//// }
////
//// // 4. 创建HTTP客户端
//// client := &http.Client{
//// Timeout: 30 * time.Minute,
//// }
////
//// // 5. 发送GET请求下载文件
//// // 注意:这里先打印下载开始信息,这行会在主函数打印版本号信息之后立即执行
//// if version == "" {
//// printDownload("正在下载: %s (版本: %s)", filename, "最新版本")
//// } else {
//// printDownload("正在下载: %s (版本: %s)", filename, version)
//// }
////
//// // 添加查询参数
//// req, err := http.NewRequest("GET", url, nil)
//// if err != nil {
//// return fmt.Errorf("创建请求失败: %v", err)
//// }
////
//// q := req.URL.Query()
//// q.Add("filename", filename)
//// if version != "" {
//// q.Add("version", version)
//// }
//// req.URL.RawQuery = q.Encode()
////
//// resp, err := client.Do(req)
//// if err != nil {
//// return fmt.Errorf("请求失败: %v", err)
//// }
//// defer resp.Body.Close()
////
//// if resp.StatusCode != http.StatusOK {
//// return fmt.Errorf("服务器返回错误状态码: %d", resp.StatusCode)
//// }
////
//// // 6. 获取文件大小
//// totalSize := resp.ContentLength
//// if totalSize > 0 {
//// fmt.Printf(ColorGray+"文件大小: %.2f MB\n"+ColorReset, float64(totalSize)/1024/1024)
//// }
////
//// // 7. 创建临时文件
//// out, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
//// if err != nil {
//// return fmt.Errorf("创建临时文件失败: %v", err)
//// }
//// defer out.Close()
////
//// // 8. 确保下载失败时清理临时文件
//// downloadSuccess := false
//// defer func() {
//// if !downloadSuccess {
//// os.Remove(tempPath)
//// }
//// }()
////
//// // 9. 手动进度显示
//// startTime := time.Now()
//// var downloaded int64 = 0
//// var lastUpdate time.Time
//// lastUpdate = time.Now()
////
//// // 10. 创建缓冲区读取
//// buf := make([]byte, 32*1024)
//// for {
//// n, err := resp.Body.Read(buf)
//// if n > 0 {
//// // 写入临时文件
//// if _, writeErr := out.Write(buf[:n]); writeErr != nil {
//// return fmt.Errorf("写入文件失败: %v", writeErr)
//// }
////
//// // 更新下载量
//// downloaded += int64(n)
////
//// // 每500ms更新一次进度
//// if time.Since(lastUpdate) > 500*time.Millisecond || err != nil {
//// if totalSize > 0 {
//// percent := float64(downloaded) / float64(totalSize) * 100
//// fmt.Printf("\r"+ColorCyan+"下载进度: %.2f%% (%.2f/%.2f MB)"+ColorReset,
//// percent,
//// float64(downloaded)/1024/1024,
//// float64(totalSize)/1024/1024)
//// } else {
//// fmt.Printf("\r"+ColorCyan+"已下载: %.2f MB"+ColorReset, float64(downloaded)/1024/1024)
//// }
//// lastUpdate = time.Now()
//// }
//// }
////
//// if err != nil {
//// if err != io.EOF {
//// return fmt.Errorf("读取失败: %v", err)
//// }
//// break
//// }
//// }
////
//// // 下载完成确保进度显示100%
//// if totalSize > 0 && downloaded < totalSize {
//// downloaded = totalSize
//// }
//// fmt.Printf("\r"+ColorGreen+"下载进度: 100.00%% (%.2f/%.2f MB)\n"+ColorReset,
//// float64(downloaded)/1024/1024,
//// float64(totalSize)/1024/1024)
////
//// // 11. 关闭临时文件
//// out.Close()
////
//// // 12. 验证下载的文件大小
//// if totalSize > 0 {
//// if fi, err := os.Stat(tempPath); err == nil {
//// if fi.Size() != totalSize {
//// return fmt.Errorf("文件大小不匹配: 期望 %d, 实际 %d", totalSize, fi.Size())
//// }
//// }
//// }
////
//// // 13. 将临时文件重命名为目标文件
//// for i := 0; i < 3; i++ {
//// if err := os.Rename(tempPath, outputPath); err == nil {
//// downloadSuccess = true
//// break
//// }
////
//// if i == 2 {
//// // 尝试直接复制
//// if err := copyFile(tempPath, outputPath); err != nil {
//// return fmt.Errorf("保存文件失败: %v", err)
//// }
//// downloadSuccess = true
//// }
////
//// time.Sleep(500 * time.Millisecond)
//// }
////
//// elapsed := time.Since(startTime)
//// printSuccess("下载完成: %s (耗时: %v)", filepath.Base(outputPath), elapsed.Round(time.Second))
////
//// // 14. 验证最终文件
//// if _, err := os.Stat(outputPath); err != nil {
//// return fmt.Errorf("最终文件验证失败: %v", err)
//// }
////
//// return nil
////}
//
//// 主下载函数
//func downloadDLL(url, outputPath, filename, version string) error {
// // 1. 确保目录存在
// dir := filepath.Dir(outputPath)
// if err := os.MkdirAll(dir, 0755); err != nil {
// return fmt.Errorf("创建目录失败: %v", err)
// }
//
// // 2. 创建临时文件路径
// tempPath := outputPath + ".tmp"
//
// // 3. 清理可能存在的旧临时文件
// if _, err := os.Stat(tempPath); err == nil {
// os.Remove(tempPath)
// }
//
// // 4. 检查目标文件是否存在
// if _, err := os.Stat(outputPath); err == nil {
// backupPath := outputPath + ".bak"
// if err := os.Rename(outputPath, backupPath); err != nil {
// // 重命名失败,尝试直接删除
// for i := 0; i < 3; i++ {
// if err := os.Remove(outputPath); err == nil {
// break
// }
// if i == 2 {
// if strings.Contains(err.Error(), "Access is denied") {
// return fmt.Errorf("文件被其他程序占用,请关闭可能使用此文件的程序后再试: %s", outputPath)
// }
// return fmt.Errorf("无法删除已存在的文件: %v", err)
// }
// time.Sleep(1 * time.Second)
// }
// } else {
// // 异步清理备份文件
// go func() {
// time.Sleep(30 * time.Second)
// if _, err := os.Stat(backupPath); err == nil {
// os.Remove(backupPath)
// }
// }()
// }
// }
//
// // 5. 打印下载信息
// if version == "" {
// printDownload("正在下载: %s (版本: 最新版本)", filename)
// } else {
// printDownload("正在下载: %s (版本: %s)", filename, version)
// }
//
// // 6. 首先尝试获取文件大小信息HEAD请求
// headClient := &http.Client{
// Timeout: 10 * time.Second,
// }
//
// headReq, err := http.NewRequest("HEAD", url, nil)
// if err != nil {
// printError("创建HEAD请求失败使用默认超时设置: %v", err)
// } else {
// // 添加查询参数
// q := headReq.URL.Query()
// q.Add("filename", filename)
// if version != "" {
// q.Add("version", version)
// }
// headReq.URL.RawQuery = q.Encode()
// headReq.Header.Set("User-Agent", "DLL-Downloader/1.0")
//
// resp, err := headClient.Do(headReq)
// if err == nil && resp.StatusCode == http.StatusOK {
// if contentLength := resp.ContentLength; contentLength > 0 {
// fmt.Printf(ColorGray+"获取到文件大小: %.2f MB\n"+ColorReset,
// float64(contentLength)/1024/1024)
// }
// resp.Body.Close()
// }
// }
//
// // 7. 创建长时间下载的HTTP客户端
// // 使用自定义Transport不设置Client.Timeout改用context控制
// transport := &http.Transport{
// Proxy: http.ProxyFromEnvironment,
// DialContext: (&net.Dialer{
// Timeout: 30 * time.Second,
// KeepAlive: 30 * time.Second,
// DualStack: true,
// }).DialContext,
// ForceAttemptHTTP2: true,
// MaxIdleConns: 100,
// MaxIdleConnsPerHost: 10,
// IdleConnTimeout: 90 * time.Second,
// TLSHandshakeTimeout: 15 * time.Second,
// ExpectContinueTimeout: 5 * time.Second,
// ResponseHeaderTimeout: 30 * time.Second,
// ReadBufferSize: 128 * 1024, // 128KB
// WriteBufferSize: 128 * 1024,
// // 禁用读写超时,通过活动检测控制
// }
//
// client := &http.Client{
// Transport: transport,
// // 重要不设置Timeout使用context控制
// }
//
// // 8. 创建下载请求
// // 使用3小时的context超时但通过活动检测防止死连接
// ctx, cancel := context.WithTimeout(context.Background(), 3*time.Hour)
// defer cancel()
//
// req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
// if err != nil {
// return fmt.Errorf("创建请求失败: %v", err)
// }
//
// // 添加查询参数
// q := req.URL.Query()
// q.Add("filename", filename)
// if version != "" {
// q.Add("version", version)
// }
// req.URL.RawQuery = q.Encode()
//
// // 添加请求头
// req.Header.Set("User-Agent", "DLL-Downloader/1.0")
// req.Header.Set("Accept", "*/*")
// req.Header.Set("Accept-Encoding", "gzip, deflate")
// req.Header.Set("Connection", "keep-alive")
//
// // 9. 发送请求
// resp, err := client.Do(req)
// if err != nil {
// if strings.Contains(err.Error(), "context deadline exceeded") {
// return fmt.Errorf("连接超时,请检查网络连接: %v", err)
// }
// return fmt.Errorf("请求失败: %v", err)
// }
// defer resp.Body.Close()
//
// if resp.StatusCode != http.StatusOK {
// body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
// return fmt.Errorf("服务器返回错误: %d - %s", resp.StatusCode, string(body))
// }
//
// // 10. 获取文件大小
// totalSize := resp.ContentLength
// if totalSize > 0 {
// fmt.Printf(ColorGray+"文件大小: %.2f MB\n"+ColorReset, float64(totalSize)/1024/1024)
//
// // 根据文件大小提供预估时间
// // 假设最低速度 50KB/s
// minSpeed := 50.0 * 1024
// estimatedTime := time.Duration(float64(totalSize)/minSpeed) * time.Second
// if estimatedTime > 30*time.Second {
// fmt.Printf(ColorGray+"预估下载时间: %v (基于50KB/s最低速度)\n"+ColorReset,
// estimatedTime.Round(time.Second))
// }
// } else {
// fmt.Println(ColorGray + "文件大小: 未知" + ColorReset)
// }
//
// // 11. 创建临时文件
// out, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
// if err != nil {
// return fmt.Errorf("创建临时文件失败: %v", err)
// }
// defer out.Close()
//
// // 12. 确保下载失败时清理临时文件
// downloadSuccess := false
// defer func() {
// if !downloadSuccess {
// os.Remove(tempPath)
// }
// }()
//
// // 13. 活动检测机制
// activityCh := make(chan time.Time, 100) // 缓冲通道,避免阻塞
// var lastActivity time.Time
// lastActivity = time.Now()
//
// // 创建活动检测的reader
// activityReader := &activityReader{
// reader: resp.Body,
// activityCh: activityCh,
// activityPtr: &lastActivity,
// }
//
// // 启动活动检测goroutine
// activityCtx, activityCancel := context.WithCancel(context.Background())
// defer activityCancel()
//
// go func() {
// ticker := time.NewTicker(30 * time.Second) // 每30秒检查一次活动
// defer ticker.Stop()
//
// for {
// select {
// case <-activityCtx.Done():
// return
// case activityTime := <-activityCh:
// lastActivity = activityTime
// case <-ticker.C:
// // 检查最近60秒内是否有活动
// if time.Since(lastActivity) > 60*time.Second {
// printError("下载活动超时60秒内没有收到数据")
// cancel() // 取消主context
// return
// }
// }
// }
// }()
//
// // 14. 下载进度显示
// startTime := time.Now()
// var downloaded int64 = 0
// var lastUpdate time.Time
// lastUpdate = time.Now()
//
// // 15. 创建缓冲区
// buf := make([]byte, 128*1024) // 128KB缓冲区
//
// // 显示初始进度
// fmt.Print(ColorCyan + "下载进度: 0.00% (0.00/0.00 MB)" + ColorReset)
//
// for {
// // 检查context是否被取消
// select {
// case <-ctx.Done():
// return fmt.Errorf("下载被取消: %v", ctx.Err())
// default:
// // 继续下载
// }
//
// n, err := activityReader.Read(buf)
// if n > 0 {
// // 写入临时文件
// if _, writeErr := out.Write(buf[:n]); writeErr != nil {
// return fmt.Errorf("写入文件失败: %v", writeErr)
// }
//
// // 更新下载量
// downloaded += int64(n)
//
// // 更新进度显示(每秒最多更新一次)
// if time.Since(lastUpdate) > 1*time.Second || err != nil {
// if totalSize > 0 {
// percent := float64(downloaded) / float64(totalSize) * 100
// elapsed := time.Since(startTime).Seconds()
// speed := 0.0
// if elapsed > 0 {
// speed = float64(downloaded) / elapsed / 1024 / 1024
// }
//
// // 计算剩余时间
// remaining := time.Duration(0)
// if speed > 0 && downloaded > 0 {
// remainingSecs := float64(totalSize-downloaded) / (float64(downloaded) / elapsed)
// remaining = time.Duration(remainingSecs) * time.Second
// }
//
// // 清除当前行并显示进度
// fmt.Printf("\r\033[K"+ColorCyan+"下载进度: %.2f%% (%.2f/%.2f MB) 速度: %.2f MB/s 剩余: %v"+ColorReset,
// percent,
// float64(downloaded)/1024/1024,
// float64(totalSize)/1024/1024,
// speed,
// remaining.Round(time.Second))
// } else {
// // 未知文件大小的情况
// elapsed := time.Since(startTime).Seconds()
// speed := 0.0
// if elapsed > 0 {
// speed = float64(downloaded) / elapsed / 1024 / 1024
// }
// fmt.Printf("\r\033[K"+ColorCyan+"已下载: %.2f MB 速度: %.2f MB/s"+ColorReset,
// float64(downloaded)/1024/1024,
// speed)
// }
// lastUpdate = time.Now()
// }
// }
//
// if err != nil {
// if err == io.EOF {
// break
// }
// // 检查是否是context取消的错误
// if ctx.Err() != nil {
// return fmt.Errorf("下载中断: %v", ctx.Err())
// }
// return fmt.Errorf("读取数据失败: %v", err)
// }
// }
//
// // 16. 下载完成,显示最终进度
// if totalSize > 0 && downloaded < totalSize {
// downloaded = totalSize // 确保显示100%
// }
//
// if totalSize > 0 {
// fmt.Printf("\r\033[K"+ColorGreen+"下载完成: 100.00%% (%.2f/%.2f MB)\n"+ColorReset,
// float64(downloaded)/1024/1024,
// float64(totalSize)/1024/1024)
// } else {
// fmt.Printf("\r\033[K"+ColorGreen+"下载完成: %.2f MB\n"+ColorReset,
// float64(downloaded)/1024/1024)
// }
//
// // 停止活动检测
// activityCancel()
//
// // 17. 验证下载的文件大小
// if totalSize > 0 {
// fi, err := os.Stat(tempPath)
// if err != nil {
// return fmt.Errorf("无法验证下载文件: %v", err)
// }
// if fi.Size() != totalSize {
// return fmt.Errorf("文件大小不匹配: 期望 %d 字节, 实际 %d 字节", totalSize, fi.Size())
// }
// }
//
// // 18. 将临时文件重命名为目标文件
// maxRetries := 5
// for i := 0; i < maxRetries; i++ {
// if err := os.Rename(tempPath, outputPath); err == nil {
// downloadSuccess = true
// break
// }
//
// if i == maxRetries-1 {
// // 最后一次尝试:使用复制方式
// if err := copyFile(tempPath, outputPath); err != nil {
// return fmt.Errorf("保存文件失败: %v", err)
// }
// downloadSuccess = true
// } else {
// // 等待后重试
// time.Sleep(500 * time.Millisecond * time.Duration(i+1))
// }
// }
//
// // 19. 验证最终文件
// fi, err := os.Stat(outputPath)
// if err != nil {
// return fmt.Errorf("最终文件验证失败: %v", err)
// }
//
// elapsed := time.Since(startTime)
// speed := float64(fi.Size()) / elapsed.Seconds() / 1024 / 1024
// printSuccess("下载完成: %s (大小: %.2f MB, 耗时: %v, 平均速度: %.2f MB/s)",
// filepath.Base(outputPath),
// float64(fi.Size())/1024/1024,
// elapsed.Round(time.Second),
// speed)
//
// return nil
//}
//
//// 活动检测读取器
//type activityReader struct {
// reader io.Reader
// activityCh chan<- time.Time
// activityPtr *time.Time
//}
//
//func (r *activityReader) Read(p []byte) (n int, err error) {
// n, err = r.reader.Read(p)
// if n > 0 {
// now := time.Now()
// r.activityCh <- now
// if r.activityPtr != nil {
// *r.activityPtr = now
// }
// }
// return
//}
//
//// 辅助函数:复制文件
//func copyFile(src, dst string) error {
// source, err := os.Open(src)
// if err != nil {
// return err
// }
// defer source.Close()
//
// destination, err := os.Create(dst)
// if err != nil {
// return err
// }
// defer destination.Close()
//
// _, err = io.Copy(destination, source)
// return err
//}
//
//// 辅助函数:检查文件是否被占用
//func isFileLocked(filepath string) bool {
// file, err := os.OpenFile(filepath, os.O_RDWR, 0666)
// if err != nil {
// return strings.Contains(err.Error(), "The process cannot access the file")
// }
// file.Close()
// return false
//}