package ssh import ( "io" "os" "path/filepath" "be.ems/src/framework/logger" gosftp "github.com/pkg/sftp" ) // SSHClientSFTP SSH客户端SFTP对象 type SSHClientSFTP struct { Client *gosftp.Client } // Close 关闭会话 func (s *SSHClientSFTP) Close() { if s.Client != nil { s.Client.Close() } } // CopyDirRemoteToLocal 复制目录-远程到本地 func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error { // 列出远程目录中的文件和子目录 remoteFiles, err := s.Client.ReadDir(remoteDir) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error()) return err } // 创建本地目录 err = os.MkdirAll(localDir, 0775) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error()) return err } // 遍历远程文件和子目录并复制到本地 for _, remoteFile := range remoteFiles { remotePath := filepath.Join(remoteDir, remoteFile.Name()) localPath := filepath.Join(localDir, remoteFile.Name()) if remoteFile.IsDir() { // 如果是子目录,则递归复制子目录 err = s.CopyDirRemoteToLocal(remotePath, localPath) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error()) continue } } else { // 如果是文件,则复制文件内容 remoteFile, err := s.Client.Open(remotePath) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error()) continue } defer remoteFile.Close() localFile, err := os.Create(localPath) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to creating local file %s: => %s", localPath, err.Error()) continue } defer localFile.Close() _, err = io.Copy(localFile, remoteFile) if err != nil { logger.Errorf("CopyDirRemoteToLocal failed to copying file contents from %s to %s: => %s", remotePath, localPath, err.Error()) continue } } } return nil } // CopyDirRemoteToLocal 复制目录-本地到远程 func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error { // 创建远程目录 err := s.Client.MkdirAll(remoteDir) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remoteDir, err.Error()) return err } // 遍历本地目录中的文件和子目录并复制到远程 err = filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error { if err != nil { return err } // 生成远程路径 remotePath := filepath.Join(remoteDir, localPath[len(localDir):]) if info.IsDir() { // 如果是子目录,则创建远程目录 err := s.Client.MkdirAll(remotePath) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error()) return nil } } else { // 如果是文件,则复制文件内容 localFile, err := os.Open(localPath) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to opening local file %s: => %s", localPath, err.Error()) return nil } defer localFile.Close() remoteFile, err := s.Client.Create(remotePath) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to creating remote file %s: => %s", remotePath, err.Error()) return nil } defer remoteFile.Close() _, err = io.Copy(remoteFile, localFile) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to copying file contents from %s to %s: => %s", localPath, remotePath, err.Error()) return nil } } return nil }) if err != nil { logger.Errorf("CopyDirLocalToRemote failed to walking local directory: => %s", err.Error()) return err } return nil } // CopyDirRemoteToLocal 复制文件-远程到本地 func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error { // 打开远程文件 remoteFile, err := s.Client.Open(remotePath) if err != nil { logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error()) return err } defer remoteFile.Close() if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil { return err } // 如果目标文件已经存在,先将目标文件重命名 // if info, err := os.Stat(localPath); err == nil && !info.IsDir() { // ext := filepath.Ext(localPath) // name := localPath[0 : len(localPath)-len(ext)] // newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext) // err := os.Rename(localPath, newName) // if err != nil { // return err // } // } // 创建本地文件 localFile, err := os.Create(localPath) if err != nil { logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error()) return err } defer localFile.Close() // 复制文件内容 _, err = io.Copy(localFile, remoteFile) if err != nil { logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error()) return err } return nil } // CopyDirRemoteToLocal 复制文件-本地到远程 func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error { // 打开本地文件 localFile, err := os.Open(localPath) if err != nil { logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error()) return err } defer localFile.Close() // 创建远程文件 remoteFile, err := s.Client.Create(remotePath) if err != nil { logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error()) return err } defer remoteFile.Close() // 复制文件内容 _, err = io.Copy(remoteFile, localFile) if err != nil { logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error()) return err } return nil }