golang實現(xiàn)ftp功能簡單又實用(示例代碼)
更新時間:2025年12月27日 09:10:50 作者:無知就要求知
本文介紹了如何使用Go語言實現(xiàn)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實現(xiàn)ftp功能簡單又實用的文章就介紹到這了,更多相關golang實現(xiàn)ftp功能內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
以Golang為例詳解AST抽象語法樹的原理與實現(xiàn)
AST?使用樹狀結構來表達編程語言的結構,樹中的每一個節(jié)點都表示源碼中的一個結構,本文將以GO語言為例,為大家介紹一下AST抽象語法樹的原理與實現(xiàn),希望對大家有所幫助2024-01-01
Go項目中使用Casbin實現(xiàn)RBAC權限管理教程
本文主要介紹了Go項目中使用Casbin實現(xiàn)RBAC權限管理教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2026-01-01

