@@ -9,14 +9,20 @@ import (
99 "net/http"
1010 "net/url"
1111 "os"
12+ "os/exec"
1213 "path/filepath"
14+ "runtime"
1315 "strings"
1416
1517 "github.com/klauspost/compress/zstd"
1618)
1719
1820const defaultDownloadUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 LoRAPilotInstaller/1.0"
1921
22+ var currentGOOS = runtime .GOOS
23+ var execLookPath = exec .LookPath
24+ var execCommandContext = exec .CommandContext
25+
2026func DownloadFile (ctx context.Context , client * http.Client , sourceURL , destination string ) error {
2127 if sourceURL == "" {
2228 return fmt .Errorf ("download url is empty" )
@@ -32,6 +38,12 @@ func DownloadFile(ctx context.Context, client *http.Client, sourceURL, destinati
3238 return copyFile (localPath , destination )
3339 }
3440
41+ if shouldUseCurlDownloader (sourceURL ) {
42+ if err := downloadWithCurl (ctx , sourceURL , destination ); err == nil {
43+ return nil
44+ }
45+ }
46+
3547 req , err := http .NewRequestWithContext (ctx , http .MethodGet , sourceURL , nil )
3648 if err != nil {
3749 return fmt .Errorf ("build download request: %w" , err )
@@ -61,6 +73,55 @@ func DownloadFile(ctx context.Context, client *http.Client, sourceURL, destinati
6173 return nil
6274}
6375
76+ func shouldUseCurlDownloader (sourceURL string ) bool {
77+ if currentGOOS != "windows" {
78+ return false
79+ }
80+ parsed , err := url .Parse (sourceURL )
81+ if err != nil {
82+ return false
83+ }
84+ if parsed .Scheme != "http" && parsed .Scheme != "https" {
85+ return false
86+ }
87+ _ , err = execLookPath ("curl.exe" )
88+ return err == nil
89+ }
90+
91+ func buildCurlDownloadArgs (sourceURL , destination string ) []string {
92+ return []string {
93+ "--silent" ,
94+ "--show-error" ,
95+ "--fail" ,
96+ "--location" ,
97+ "--retry" ,
98+ "5" ,
99+ "--retry-delay" ,
100+ "2" ,
101+ "--retry-all-errors" ,
102+ "--user-agent" ,
103+ defaultDownloadUserAgent ,
104+ "--header" ,
105+ "Accept: */*" ,
106+ "--output" ,
107+ destination ,
108+ sourceURL ,
109+ }
110+ }
111+
112+ func downloadWithCurl (ctx context.Context , sourceURL , destination string ) error {
113+ cmd := execCommandContext (ctx , "curl.exe" , buildCurlDownloadArgs (sourceURL , destination )... )
114+ output , err := cmd .CombinedOutput ()
115+ if err != nil {
116+ message := strings .TrimSpace (string (output ))
117+ if message == "" {
118+ message = err .Error ()
119+ }
120+ return fmt .Errorf ("curl download %s: %s" , sourceURL , message )
121+ }
122+ return nil
123+ }
124+
64125func VerifySHA256File (path , want string ) error {
65126 hashValue , err := SHA256File (path )
66127 if err != nil {
0 commit comments