go-util/sftp.go

99 lines
1.9 KiB
Go

package util
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"golang.org/x/crypto/ssh"
"github.com/pkg/sftp"
)
type SftpStorageOpts struct {
Host string
Port int
User string
Password string
// Logger *slog.Logger
}
type SftpStorage struct {
SftpStorageOpts
sshcon *ssh.Client
Sftpcon *sftp.Client
}
func NewSsftp(c SftpStorageOpts) SftpStorage {
return SftpStorage{SftpStorageOpts: c}
}
// caller needs to defer
func (s *SftpStorage) Close() {
s.Sftpcon.Close()
s.sshcon.Close()
}
func (s *SftpStorage) Connect() (err error) {
var auths []ssh.AuthMethod
if s.Password != "" {
auths = append(auths, ssh.Password(s.Password))
}
// Initialize client configuration
config := ssh.ClientConfig{
User: s.User,
Auth: auths,
// ignore host key check
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
addr := fmt.Sprintf("%s:%d", s.Host, s.Port)
// Connect to server
s.sshcon, err = ssh.Dial("tcp", addr, &config)
if err != nil {
return fmt.Errorf("failed to connecto to [%s]: %v", addr, err)
}
// Create new SFTP client
s.Sftpcon, err = sftp.NewClient(s.sshcon)
if err != nil {
return fmt.Errorf("unable to start SFTP subsystem [%s]: %v", addr, err)
}
return
}
func (s *SftpStorage) UploadFile(localFile, remoteFile string) (err error) {
srcFile, err := os.Open(localFile)
if err != nil {
return fmt.Errorf("unable to open localfile file: %v", err)
}
defer srcFile.Close()
parent := filepath.Dir(remoteFile)
path := string(filepath.Separator)
dirs := strings.Split(parent, path)
for _, dir := range dirs {
path = filepath.Join(path, dir)
s.Sftpcon.Mkdir(path)
}
dstFile, err := s.Sftpcon.OpenFile(remoteFile, (os.O_WRONLY | os.O_CREATE | os.O_TRUNC))
if err != nil {
return fmt.Errorf("unable to open remote file: %v", err)
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return fmt.Errorf("unable to upload file: %v", err)
}
return
}