Go实现SFTP客户端

我将提供一个封装了 SFTP 客户端操作的简单例子,以确保通用性。这个例子包括连接、断开连接、上传文件、下载文件、列出目录和创建目录的基本操作。

这个 SFTPClient 结构体包含了一个 *sftp.Client 字段,我们通过实现方法来提供基本的 SFTP 操作。NewClient 函数用于创建和返回一个新的 SFTPClient 实例。其他函数封装了上传、下载、列出目录和创建目录等操作。

请注意,HostKeyCallback 设置为 ssh.InsecureIgnoreHostKey() 会忽略服务器的 SSH 主机密钥验证,这在生产环境中是不安全的。在实际使用中,应该提供一个适当的回调函数来验证服务器的主机密钥。

go 复制代码
package main

import (
	"fmt"
	"io"
	"log"
	"os"

	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

type SFTPClient struct {
	client *sftp.Client
}

// NewClient 创建一个新的 SFTP 客户端实例并连接到服务器
func NewClient(username, password, host string, port int) (*SFTPClient, error) {
	// 设置 SSH 配置
	config := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 注意:这不安全,并且应该在生产环境中避免使用
	}

	// 连接到 SSH 服务器
	addr := fmt.Sprintf("%s:%d", host, port)
	sshConn, err := ssh.Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}

	// 启动 SFTP 子系统
	client, err := sftp.NewClient(sshConn)
	if err != nil {
		return nil, err
	}

	return &SFTPClient{client: client}, nil
}

// Close 关闭 SFTP 客户端连接
func (c *SFTPClient) Close() error {
	return c.client.Close()
}

// UploadFile 将本地文件上传到 SFTP 服务器
func (c *SFTPClient) UploadFile(localPath, remotePath string) error {
	srcFile, err := os.Open(localPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	dstFile, err := c.client.Create(remotePath)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	_, err = io.Copy(dstFile, srcFile)
	return err
}

// DownloadFile 从 SFTP 服务器下载文件到本地
func (c *SFTPClient) DownloadFile(remotePath, localPath string) error {
	srcFile, err := c.client.Open(remotePath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	dstFile, err := os.Create(localPath)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	_, err = io.Copy(dstFile, srcFile)
	return err
}

// ListDirectory 列出 SFTP 服务器上的目录内容
func (c *SFTPClient) ListDirectory(remotePath string) ([]os.FileInfo, error) {
	return c.client.ReadDir(remotePath)
}

// MakeDirectory 在 SFTP 服务器上创建目录
func (c *SFTPClient) MakeDirectory(remotePath string) error {
	return c.client.Mkdir(remotePath)
}

// RemoveFile 删除 SFTP 服务器上的文件
func (c *SFTPClient) RemoveFile(remotePath string) error {
	return c.client.Remove(remotePath)
}

// RemoveDirectory 删除 SFTP 服务器上的目录
func (c *SFTPClient) RemoveDirectory(remotePath string) error {
	return c.client.RemoveDirectory(remotePath)
}

func main() {
	// SFTP 服务器设置
	host := "127.0.0.1"
	port := 9527
	username := "root"
	password := "123456"

	// 初始化 SFTP 客户端
	client, err := NewClient(username, password, host, port)
	if err != nil {
		log.Fatalf("Error initializing SFTP client: %v", err)
	}
	defer client.Close()

	// 上传本地文件到 SFTP 服务器
	localFilePath := "./localfile.txt"
	remoteFilePath := "./remotefile.txt"
	err = client.UploadFile(localFilePath, remoteFilePath)
	if err != nil {
		log.Fatalf("Error uploading file: %v", err)
	}
	fmt.Println("File uploaded successfully.")

	// 从 SFTP 服务器下载文件到本地
	localDownloadPath := "./localfile_downloaded.txt"
	err = client.DownloadFile(remoteFilePath, localDownloadPath)
	if err != nil {
		log.Fatalf("Error downloading file: %v", err)
	}
	fmt.Println("File downloaded successfully.")

	// 列出 SFTP 服务器上的目录内容
	remoteDirectory := "./"
	files, err := client.ListDirectory(remoteDirectory)
	if err != nil {
		log.Fatalf("Error listing directory: %v", err)
	}
	fmt.Println("Directory listing:")
	for _, file := range files {
		fmt.Printf(" - %s\n", file.Name())
	}

	// 在 SFTP 服务器上创建目录
	remoteNewDirectory := "./newdir"
	err = client.MakeDirectory(remoteNewDirectory)
	if err != nil {
		log.Fatalf("Error creating directory: %v", err)
	}
	fmt.Println("Directory created successfully.")

	// 删除 SFTP 服务器上的文件
	err = client.RemoveFile(remoteFilePath)
	if err != nil {
		log.Fatalf("Error removing file: %v", err)
	}
	fmt.Println("File removed successfully.")

	// 删除 SFTP 服务器上的目录
	err = client.RemoveDirectory(remoteNewDirectory)
	if err != nil {
		log.Fatalf("Error removing directory: %v", err)
	}
	fmt.Println("Directory removed successfully.")
}

在这个示例中,我们首先通过 NewClient 函数初始化了一个 SFTP 客户端连接。然后,我们使用该客户端上传一个文件,下载一个文件,列出目录内容,以及在 SFTP 服务器上创建一个新目录。每个操作之后,我们都检查错误并在终端输出结果。

在实际部署中,您可能需要替换 host, port, username, 和 password 变量的值以匹配您的 SFTP 服务器的凭据和地址。此外,您也需要确保本地文件路径和远程文件路径是正确的。

请记住,错误处理非常重要,特别是在处理文件操作时。在生产环境中,还应该考虑更安全的认证方法,比如使用 SSH 密钥,以及对服务器主机密钥进行适当的验证。

相关推荐
呼Lu噜1 分钟前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
bing_1586 分钟前
为什么选择 Spring Boot? 它是如何简化单个微服务的创建、配置和部署的?
spring boot·后端·微服务
小臭希7 分钟前
Java——琐碎知识点一
java·开发语言
张帅涛_6668 分钟前
golang goroutine(协程)和 channel(管道) 案例解析
jvm·golang·go
学c真好玩18 分钟前
Django创建的应用目录详细解释以及如何操作数据库自动创建表
后端·python·django
Asthenia041219 分钟前
GenericObjectPool——重用你的对象
后端
Piper蛋窝29 分钟前
Go 1.18 相比 Go 1.17 有哪些值得注意的改动?
后端
excel43 分钟前
招幕技术人员
前端·javascript·后端
盖世英雄酱581361 小时前
什么是MCP
后端·程序员
淋一遍下雨天1 小时前
Spark Streaming核心编程总结(四)
java·开发语言·数据库