- Implemented advanced download utility with proxy support for SOCKS5 and HTTP protocols - Added progress tracking with human-readable file size and download percentage - Updated go.mod and go.sum to include new dependencies for proxy and networking - Created flexible proxy client generation for different proxy types - Improved error handling and logging in download process
122 lines
2.8 KiB
Go
122 lines
2.8 KiB
Go
package cmd
|
||
|
||
import (
|
||
"agent-wdd/log"
|
||
"agent-wdd/utils"
|
||
"context"
|
||
"fmt"
|
||
"net"
|
||
"net/http"
|
||
"net/url"
|
||
"time"
|
||
|
||
"github.com/spf13/cobra"
|
||
"golang.org/x/net/proxy"
|
||
)
|
||
|
||
// 示例:添加download子命令
|
||
func addDownloadSubcommands(cmd *cobra.Command) {
|
||
proxyCmd := &cobra.Command{
|
||
Use: "proxy [proxyUrl] [url] [dest]",
|
||
Short: "使用代理下载 支持socks5代理 http代理",
|
||
Args: cobra.ExactArgs(3),
|
||
Run: func(cmd *cobra.Command, args []string) {
|
||
proxyURL := args[0]
|
||
fileURL := args[1]
|
||
destPath := args[2]
|
||
|
||
log.Info("Downloading using proxy: %s -> from %s to %s\n", proxyURL, fileURL, destPath)
|
||
|
||
// 创建带代理的HTTP客户端
|
||
client, err := createProxyClient(proxyURL)
|
||
if err != nil {
|
||
log.Error("创建代理客户端失败: %v", err)
|
||
}
|
||
|
||
// 执行下载
|
||
downloadOk, resultLog := utils.DownloadFileWithClient(client, fileURL, destPath)
|
||
if !downloadOk {
|
||
log.Error("下载失败: %v", resultLog)
|
||
} else {
|
||
log.Info("文件下载完成")
|
||
}
|
||
|
||
},
|
||
}
|
||
|
||
cmd.Run = func(cmd *cobra.Command, args []string) {
|
||
|
||
if len(args) == 0 {
|
||
log.Error("请输入下载地址")
|
||
return
|
||
} else if len(args) == 1 {
|
||
args = append(args, ".")
|
||
}
|
||
|
||
log.Info("Downloading without proxy: %s -> %s\n", args[0], args[1])
|
||
|
||
downloadOk, resultLog := utils.DownloadFile(args[0], args[1])
|
||
if !downloadOk {
|
||
log.Error("下载失败: %s", resultLog)
|
||
} else {
|
||
log.Info("下载成功: %s", args[1])
|
||
}
|
||
|
||
}
|
||
|
||
cmd.AddCommand(proxyCmd)
|
||
}
|
||
|
||
// 创建带代理的HTTP客户端
|
||
func createProxyClient(proxyURL string) (*http.Client, error) {
|
||
parsedURL, err := url.Parse(proxyURL)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("无效的代理URL: %w", err)
|
||
}
|
||
|
||
switch parsedURL.Scheme {
|
||
case "socks5":
|
||
return createSocks5Client(parsedURL)
|
||
case "http", "https":
|
||
return createHTTPClient(parsedURL), nil
|
||
default:
|
||
return nil, fmt.Errorf("不支持的代理协议: %s", parsedURL.Scheme)
|
||
}
|
||
}
|
||
|
||
// 创建SOCKS5代理客户端
|
||
func createSocks5Client(proxyURL *url.URL) (*http.Client, error) {
|
||
var auth *proxy.Auth
|
||
if proxyURL.User != nil {
|
||
password, _ := proxyURL.User.Password()
|
||
auth = &proxy.Auth{
|
||
User: proxyURL.User.Username(),
|
||
Password: password,
|
||
}
|
||
}
|
||
|
||
dialer, err := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建SOCKS5拨号器失败: %w", err)
|
||
}
|
||
|
||
return &http.Client{
|
||
Transport: &http.Transport{
|
||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||
return dialer.Dial(network, addr)
|
||
},
|
||
},
|
||
Timeout: 10 * time.Second,
|
||
}, nil
|
||
}
|
||
|
||
// 创建HTTP代理客户端
|
||
func createHTTPClient(proxyURL *url.URL) *http.Client {
|
||
return &http.Client{
|
||
Transport: &http.Transport{
|
||
Proxy: http.ProxyURL(proxyURL),
|
||
},
|
||
Timeout: 30 * time.Minute,
|
||
}
|
||
}
|