99 lines
1.9 KiB
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
|
||
|
}
|