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 密钥,以及对服务器主机密钥进行适当的验证。

相关推荐
liu****5 分钟前
11.字符函数和字符串函数(一)
linux·运维·c语言·开发语言·数据结构·算法
hmbbcsm6 分钟前
练习python题目小记(七)
开发语言·python
aini_lovee7 分钟前
基于UERD算法的JPEG图像隐写MATLAB实现
开发语言·算法·matlab
小周在成长8 分钟前
Java 匿名内部类简明指南(重点)
后端
郑州光合科技余经理14 分钟前
技术架构:跑腿配送系统海外版源码全解析
java·开发语言·前端·数据库·架构·uni-app·php
繁华似锦respect19 分钟前
HTTPS 中 TLS 协议详细过程 + 数字证书/签名深度解析
开发语言·c++·网络协议·http·单例模式·设计模式·https
czlczl2002092521 分钟前
SpringBoot手动配置:WebMvcConfigurer接口实现类的生效原理
java·spring boot·后端
程序员皮皮林22 分钟前
SpringBoot + nmap4j 获取端口信息
java·spring boot·后端
小二·23 分钟前
Spring框架入门:Spring 中注解支持详解
java·后端·spring
坐吃山猪24 分钟前
Electron03-桌面文件夹
开发语言·javascript·ecmascript