github.com/rudderlabs/rudder-go-kit@v0.30.0/sftp/sftp.go (about) 1 package sftp 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 9 "golang.org/x/crypto/ssh" 10 ) 11 12 const ( 13 // PasswordAuth indicates password-based authentication 14 PasswordAuth = "passwordAuth" 15 // KeyAuth indicates key-based authentication 16 KeyAuth = "keyAuth" 17 ) 18 19 // FileManager is an interface for managing files on a remote server 20 type FileManager interface { 21 Upload(localFilePath, remoteDir string) error 22 Download(remoteFilePath, localDir string) error 23 Delete(remoteFilePath string) error 24 } 25 26 // fileManagerImpl is a real implementation of FileManager 27 type fileManagerImpl struct { 28 client Client 29 } 30 31 func NewFileManager(sshClient *ssh.Client) (FileManager, error) { 32 sftpClient, err := newSFTPClient(sshClient) 33 if err != nil { 34 return nil, fmt.Errorf("cannot create SFTP client: %w", err) 35 } 36 return &fileManagerImpl{client: sftpClient}, nil 37 } 38 39 // Upload uploads a file to the remote server 40 func (fm *fileManagerImpl) Upload(localFilePath, remoteFilePath string) error { 41 localFile, err := os.Open(localFilePath) 42 if err != nil { 43 return fmt.Errorf("cannot open local file: %w", err) 44 } 45 defer func() { 46 _ = localFile.Close() 47 }() 48 49 // Create the directory if it does not exist 50 remoteDir := filepath.Dir(remoteFilePath) 51 if err := fm.client.MkdirAll(remoteDir); err != nil { 52 return fmt.Errorf("cannot create remote directory: %w", err) 53 } 54 55 remoteFile, err := fm.client.OpenFile(remoteFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC) 56 if err != nil { 57 return fmt.Errorf("cannot create remote file: %w", err) 58 } 59 defer func() { 60 _ = remoteFile.Close() 61 }() 62 63 _, err = io.Copy(remoteFile, localFile) 64 if err != nil { 65 return fmt.Errorf("error copying file: %w", err) 66 } 67 68 return nil 69 } 70 71 // Download downloads a file from the remote server 72 func (fm *fileManagerImpl) Download(remoteFilePath, localDir string) error { 73 remoteFile, err := fm.client.OpenFile(remoteFilePath, os.O_RDONLY) 74 if err != nil { 75 return fmt.Errorf("cannot open remote file: %w", err) 76 } 77 defer func() { 78 _ = remoteFile.Close() 79 }() 80 81 localFileName := filepath.Join(localDir, filepath.Base(remoteFilePath)) 82 localFile, err := os.Create(localFileName) 83 if err != nil { 84 return fmt.Errorf("cannot create local file: %w", err) 85 } 86 defer func() { 87 _ = localFile.Close() 88 }() 89 90 _, err = io.Copy(localFile, remoteFile) 91 if err != nil { 92 return fmt.Errorf("cannot copy remote file content to local file: %w", err) 93 } 94 95 return nil 96 } 97 98 // Delete deletes a file on the remote server 99 func (fm *fileManagerImpl) Delete(remoteFilePath string) error { 100 err := fm.client.Remove(remoteFilePath) 101 if err != nil { 102 return fmt.Errorf("cannot delete file: %w", err) 103 } 104 105 return nil 106 }