123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- package send
- import (
- "context"
- "fmt"
- "github.com/gogf/gf/v2/frame/g"
- "github.com/pkg/sftp"
- "golang.org/x/crypto/ssh"
- "io"
- "io/fs"
- "os"
- "path/filepath"
- "time"
- )
- func UpLoadFilesToSftp(ctx context.Context, dir string) (int, []string) {
- // SFTP 连接配置
- var (
- config = &ssh.ClientConfig{
- User: g.Cfg().MustGet(ctx, "sftp.user").String(), // 替换为你的用户名
- Auth: []ssh.AuthMethod{
- ssh.Password(g.Cfg().MustGet(ctx, "sftp.pwd").String()), // 替换为你的密码
- },
- HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 生产环境应使用 ssh.FixedHostKey
- Timeout: 30 * time.Second,
- }
- successNum int
- failPath []string
- )
- // 使用 fs.WalkDir
- fs.WalkDir(os.DirFS(dir), ".", func(path string, d fs.DirEntry, err error) error {
- if err != nil {
- g.Log().Infof(ctx, "访问路径 %q 失败: %v", path, err)
- return nil
- }
- if !d.IsDir() {
- // 获取文件信息
- info, err := d.Info()
- if err != nil {
- g.Log().Infof(ctx, "获取文件信息失败: %v", err)
- return nil
- }
- fullPath := filepath.Join(dir, path)
- g.Log().Infof(ctx, "文件: %s (大小: %d bytes)", fullPath, info.Size())
- // 上传文件
- uploadErr := uploadToSFTP(config, g.Cfg().MustGet(ctx, "sftp.addr").String(), fullPath, fullPath)
- if uploadErr != nil {
- failPath = append(failPath, fullPath)
- g.Log().Errorf(ctx, "%s 文件上传失败: %s", fullPath, uploadErr.Error())
- } else {
- successNum++
- g.Log().Infof(ctx, "%s 文件上传成功!", fullPath)
- }
- }
- return nil
- })
- return successNum, failPath
- }
- // 上传文件到SFTP服务器
- func uploadToSFTP(config *ssh.ClientConfig, addr, localPath, remotePath string) error {
- // 1. 建立SSH连接
- sshClient, err := ssh.Dial("tcp", addr, config)
- if err != nil {
- return fmt.Errorf("SSH连接失败: %w", err)
- }
- defer sshClient.Close()
- // 2. 创建SFTP客户端
- sftpClient, err := sftp.NewClient(sshClient)
- if err != nil {
- return fmt.Errorf("创建SFTP客户端失败: %w", err)
- }
- defer sftpClient.Close()
- // 3. 打开本地文件
- localFile, err := os.Open(localPath)
- if err != nil {
- return fmt.Errorf("打开本地文件失败: %w", err)
- }
- defer localFile.Close()
- // 4. 确保远程目录存在
- remoteDir := filepath.Dir(remotePath)
- if err := sftpClient.MkdirAll(remoteDir); err != nil {
- return fmt.Errorf("创建远程目录失败: %w", err)
- }
- // 5. 创建远程文件
- remoteFile, err := sftpClient.Create(remotePath)
- if err != nil {
- return fmt.Errorf("创建远程文件失败: %w", err)
- }
- defer remoteFile.Close()
- // 6. 复制文件内容
- if _, err := io.Copy(remoteFile, localFile); err != nil {
- return fmt.Errorf("复制文件内容失败: %w", err)
- }
- return nil
- }
|