feat: 新增fstp文件传输工具包

This commit is contained in:
TsMask
2024-04-11 17:04:23 +08:00
parent 9c8c12e443
commit 513a5bb5fe
4 changed files with 272 additions and 11 deletions

View File

@@ -1,8 +1,10 @@
package parse
import (
"encoding/json"
"fmt"
"image/color"
"os"
"reflect"
"regexp"
"strconv"
@@ -10,6 +12,7 @@ import (
"time"
"github.com/robfig/cron/v3"
"gopkg.in/yaml.v3"
)
// Number 解析数值型
@@ -165,3 +168,58 @@ func Color(colorStr string) *color.RGBA {
A: 255, // 不透明
}
}
// ConvertConfigToMap 将配置内容转换为Map结构数据
//
// configType 类型支持txt json yaml yml
func ConvertConfigToMap(configType, content string) (map[string]any, error) {
// 类型支持viper.SupportedExts
// config := viper.New()
// config.SetConfigType(configType)
// err := config.ReadConfig(bytes.NewBuffer([]byte(content)))
// return config.AllSettings(), err
var configMap map[string]interface{}
var err error
if configType == "txt" {
configMap = map[string]interface{}{
"txt": content,
}
}
if configType == "yaml" || configType == "yml" {
err = yaml.Unmarshal([]byte(content), &configMap)
}
if configType == "json" {
err = json.Unmarshal([]byte(content), &configMap)
}
return configMap, err
}
// ConvertConfigToFile 将数据写入到指定文件内
//
// configType 类型支持txt json yaml yml
func ConvertConfigToFile(configType, filePath string, data any) error {
// viper.SupportedExts
// config := viper.New()
// config.SetConfigType(configType)
// for key, value := range mapData {
// config.Set(key, value)
// }
// return config.WriteConfigAs(filePath)
var dataByte []byte
var err error
if configType == "" || configType == "txt" {
dataByte = []byte(data.(string))
}
if configType == "yaml" || configType == "yml" {
dataByte, err = yaml.Marshal(data)
}
if configType == "json" {
dataByte, err = json.Marshal(data)
}
if err != nil {
return err
}
return os.WriteFile(filePath, dataByte, 0644)
}

View File

@@ -6,12 +6,14 @@ import (
"io"
"os"
"os/user"
"path/filepath"
"strings"
"sync"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/cmd"
gosftp "github.com/pkg/sftp"
gossh "golang.org/x/crypto/ssh"
)
@@ -239,12 +241,11 @@ func (s *SSHClientSession) Write(cmd string) (int, error) {
return s.Stdin.Write([]byte(cmd))
}
// Read 读取结果 等待一会才有结果
// Read 读取结果
func (s *SSHClientSession) Read() []byte {
if s.Stdout == nil {
return []byte{}
}
// time.Sleep(300 * time.Millisecond)
bs := s.Stdout.Bytes()
if len(bs) > 0 {
s.Stdout.Reset()
@@ -253,15 +254,6 @@ func (s *SSHClientSession) Read() []byte {
return []byte{}
}
// CombinedOutput 发送命令带结果返回
func (s *SSHClientSession) CombinedOutput(cmd string) (string, error) {
n, err := s.Write(cmd)
if n == 0 || err != nil {
return "", err
}
return string(s.Read()), nil
}
// singleWriter SSH客户端会话消息
type singleWriter struct {
b bytes.Buffer
@@ -283,3 +275,204 @@ func (w *singleWriter) Reset() {
defer w.mu.Unlock()
w.b.Reset()
}
// NewClientSFTP 创建SSH客户端SFTP对象
func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
sftpClient, err := gosftp.NewClient(c.Client)
if err != nil {
logger.Errorf("NewClientSFTP failed to create sftp: => %s", err.Error())
return nil, err
}
return &SSHClientSFTP{
Client: sftpClient,
}, nil
}
// 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, 0755)
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 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
}