golang实现ftp功能简单又实用(示例代码)
更新时间:2025年12月27日 09:10:50 作者:无知就要求知
本文介绍了如何使用Go语言实现FTP功能,包括加载配置文件和处理FTP部分,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
配置文件部分:
FtpServer:
ListenAddr: ":2121"
ListenDir: "/data/ftpwww" # ftp目录
PassivePortRange: # end必须大于start,否则会panic, 非被动模式不用配置
Start: 3121
End: 3124
ListenUsers: # ftp账号
- Username: ftpadmin
Password: "123456..."
- Username: ftpadmin
Password: "yueduo-654321..."加载配置文件
package config
import (
"fmt"
"gopkg.in/yaml.v3"
"os"
)
var (
Conf Config
)
type Config struct {
...
FtpServer FtpServer `yaml:"FtpServer"`
...
}
func InitConfigFromYaml(file string) error {
if file == "" {
file = "config.yaml"
}
f, err := os.Open(file)
if err != nil {
return fmt.Errorf("配置文件打开错误.%w", err)
}
dec := yaml.NewDecoder(f)
err = dec.Decode(&Conf)
if err != nil {
return err
}
return nil
}main.go引用
//初始化配置文件
err := config.InitConfigFromYaml(f)
if err != nil {
logn.Errorf("配置文件初始化错误,file:%s 错误信息:%v", f, err)
return
}
// 加载ftp
go ftp.FtpDirver()ftp部分perm
package ftp
import (
"fmt"
"os"
)
// 加载文件权限只读
type ReadOnlyPerm struct{}
func (p *ReadOnlyPerm) GetOwner(path string) (string, error) {
return "ftp", nil
}
func (p *ReadOnlyPerm) GetGroup(path string) (string, error) {
return "ftp", nil
}
func (p *ReadOnlyPerm) GetMode(path string) (os.FileMode, error) {
// 0444: 只读(r--r--r--)
return 0444, nil
}
func (p *ReadOnlyPerm) ChOwner(path, owner string) error {
return fmt.Errorf("permission denied")
}
func (p *ReadOnlyPerm) ChGroup(path, group string) error {
return fmt.Errorf("permission denied")
}
func (p *ReadOnlyPerm) ChMode(path string, mode os.FileMode) error {
return fmt.Errorf("permission denied")
}dirver.go
package ftp
import (
"fmt"
filedriver "github.com/goftp/file-driver"
"github.com/goftp/server"
"io"
"log"
"net"
"os"
"safe-agent/config"
)
type MultiUserAuth struct {
users map[string]config.FTPUser
}
type PerUserDriverFactory struct {
users map[string]config.FTPUser
}
type PerUserFileDriver struct {
*filedriver.FileDriver
users map[string]config.FTPUser
}
func (d *PerUserFileDriver) Init(conn *server.Conn) {
// 🔥 每个用户设置自己的根目录
d.FileDriver.RootPath = config.Conf.FtpServer.ListenDir
}
func (d *PerUserFileDriver) Delete(path string) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) DeleteFile(path string) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) Rename(from, to string) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error) {
return 0, fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) Chmod(path string, mode os.FileMode) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) Remove(path string) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) RemoveDir(path string) error {
return fmt.Errorf("550 permission denied")
}
func (d *PerUserFileDriver) MakeDir(path string) error {
return fmt.Errorf("550 permission denied")
}
func (f *PerUserDriverFactory) NewDriver() (server.Driver, error) {
return &PerUserFileDriver{
FileDriver: &filedriver.FileDriver{
Perm: &ReadOnlyPerm{},
},
users: f.users,
}, nil
}
func (a *MultiUserAuth) CheckPasswd(user, pass string) (bool, error) {
u, ok := a.users[user]
if !ok {
return false, nil
}
return u.Password == pass, nil
}
func FtpDirver() {
userMap := make(map[string]config.FTPUser)
for _, u := range config.Conf.FtpServer.ListenUsers {
userMap[u.Username] = u
}
host, portStr, _ := net.SplitHostPort(config.Conf.FtpServer.ListenAddr)
port := 0
if portStr != "" {
fmt.Sscanf(portStr, "%d", &port)
}
passiveRange := config.Conf.FtpServer.PassivePortRange
passivePorts := fmt.Sprintf("%d-%d", passiveRange.Start, passiveRange.End)
opts := &server.ServerOpts{
Factory: &PerUserDriverFactory{
users: userMap,
},
PassivePorts: passivePorts,
Auth: &MultiUserAuth{users: userMap},
Port: port,
Hostname: host,
}
//log.Printf("FTP server listening on %s", config.Conf.FtpServer.ListenAddr)
fmt.Printf(
"FTP listen=%s passive_ports=%s",
config.Conf.FtpServer.ListenAddr,
passivePorts,
)
s := server.NewServer(opts)
log.Fatal(s.ListenAndServe())
}到此这篇关于golang实现ftp功能简单又实用的文章就介绍到这了,更多相关golang实现ftp功能内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:


最新评论