[golang/ftp]使用golang goftp 写一个ftp 服务器[zt]
clq
浏览(397) -
2023-09-19 14:23:30 发表
编辑
关键字:
[golang/ftp]使用golang goftp 写一个ftp 服务器[zt]
使用golang goftp 写一个ftp 服务器,只支持上传功能,其他删除。
技术标签: golang ftpserver
1,关于
ftp 是个很老的技术了。
项目需要搭建一个ftp服务器。但是还是想做点程序实现些特定的功能。
需要监听到服务上传文件啥的。
2,项目
从网上找了一个lib库:
https://github.com/goftp/server
非常方便。要是懒得自己写。还有个gui界面的。
https://github.com/goftp/ftpd
直接下载编译就行了:
还有界面。
3,代码
但是不需要那么多的功能。
只需要做一个简单的服务就行。
main.go
package main
import (
"github.com/goftp/server"
"os"
"fmt"
"github.com/lunny/log"
"github.com/Unknwon/goconfig"
)
func main() {
//读取配置文件:
cfg, _ := goconfig.LoadConfigFile("ftp.conf")
//端口
port, _ := cfg.Int("server", "port")
//使用简单的登录验证,用户名密码写死。
authUser, _ := cfg.GetValue("auth", "user")
authPassword, _ := cfg.GetValue("auth", "password")
//权限:
permOwner, _ := cfg.GetValue("perm", "owner")
permGroup, _ := cfg.GetValue("perm", "group")
//上传目录dir
rootPath, _ := cfg.GetValue("server", "dir")
_, err := os.Lstat(rootPath)
if os.IsNotExist(err) {
os.MkdirAll(rootPath, os.ModePerm)
} else if err != nil {
fmt.Println(err)
return
}
//设置权限。
factory := &dirver.PutFileOnlyDriverFactory{
rootPath,
server.NewSimplePerm(permOwner, permGroup),
}
opt := &server.ServerOpts{
Name: "go",
Factory: factory,
Port: port,
Auth: &server.SimpleAuth{authUser, authPassword},
}
// start ftp server
ftpServer := server.NewServer(opt)
log.Info("FTP Server", "1.0")
err = ftpServer.ListenAndServe()
if err != nil {
log.Fatal("Error starting server:", err)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
其中驱动,自己根据官方的重写了下:
package dirver
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/goftp/server"
"github.com/lunny/log"
)
type PutFileOnlyDriver struct {
RootPath string
server.Perm
}
type FileInfo struct {
os.FileInfo
mode os.FileMode
owner string
group string
}
func (f *FileInfo) Mode() os.FileMode {
return f.mode
}
func (f *FileInfo) Owner() string {
return f.owner
}
func (f *FileInfo) Group() string {
return f.group
}
func (driver *PutFileOnlyDriver) realPath(path string) string {
paths := strings.Split(path, "/")
return filepath.Join(append([]string{driver.RootPath}, paths...)...)
}
func (driver *PutFileOnlyDriver) Init(conn *server.Conn) {
//driver.conn = conn
}
func (driver *PutFileOnlyDriver) ChangeDir(path string) error {
rPath := driver.realPath(path)
f, err := os.Lstat(rPath)
if err != nil {
return err
}
if f.IsDir() {
return nil
}
return errors.New("Not a directory")
}
func (driver *PutFileOnlyDriver) Stat(path string) (server.FileInfo, error) {
basepath := driver.realPath(path)
rPath, err := filepath.Abs(basepath)
if err != nil {
return nil, err
}
f, err := os.Lstat(rPath)
if err != nil {
return nil, err
}
mode, err := driver.Perm.GetMode(path)
if err != nil {
return nil, err
}
if f.IsDir() {
mode |= os.ModeDir
}
owner, err := driver.Perm.GetOwner(path)
if err != nil {
return nil, err
}
group, err := driver.Perm.GetGroup(path)
if err != nil {
return nil, err
}
return &FileInfo{f, mode, owner, group}, nil
}
func (driver *PutFileOnlyDriver) ListDir(path string, callback func(server.FileInfo) error) error {
return nil
}
func (driver *PutFileOnlyDriver) DeleteDir(path string) error {
return errors.New("Not a directory")
}
func (driver *PutFileOnlyDriver) DeleteFile(path string) error {
return errors.New("Not a file")
}
func (driver *PutFileOnlyDriver) Rename(fromPath string, toPath string) error {
return errors.New("Not a file")
}
func (driver *PutFileOnlyDriver) MakeDir(path string) error {
return errors.New("Not a directory")
}
func (driver *PutFileOnlyDriver) GetFile(path string, offset int64) (int64, io.ReadCloser, error) {
return 0, nil, errors.New("Not a file")
}
func (driver *PutFileOnlyDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error) {
log.Info("############### PutFile destPath : ", destPath)
rPath := driver.realPath(destPath)
var isExist bool
f, err := os.Lstat(rPath)
if err == nil {
isExist = true
if f.IsDir() {
return 0, errors.New("A dir has the same name")
}
} else {
if os.IsNotExist(err) {
isExist = false
} else {
return 0, errors.New(fmt.Sprintln("Put File error:", err))
}
}
if appendData && !isExist {
appendData = false
}
if !appendData {
if isExist {
err = os.Remove(rPath)
if err != nil {
return 0, err
}
}
f, err := os.Create(rPath)
if err != nil {
return 0, err
}
defer f.Close()
bytes, err := io.Copy(f, data)
if err != nil {
return 0, err
}
return bytes, nil
}
of, err := os.OpenFile(rPath, os.O_APPEND|os.O_RDWR, 0660)
if err != nil {
return 0, err
}
defer of.Close()
_, err = of.Seek(0, os.SEEK_END)
if err != nil {
return 0, err
}
bytes, err := io.Copy(of, data)
if err != nil {
return 0, err
}
return bytes, nil
}
type PutFileOnlyDriverFactory struct {
RootPath string
server.Perm
}
func (factory *PutFileOnlyDriverFactory) NewDriver() (server.Driver, error) {
return &PutFileOnlyDriver{factory.RootPath, factory.Perm}, nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
把几个接口屏蔽了。其中配置文件:
[server]
port=21
dir=file
[auth]
user=ftpuser
password=ftpuser
[perm]
owner=root
group=root
1
2
3
4
5
6
7
8
9
10
11
4,总结
其中上传方法:
func (driver *PutFileOnlyDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error) {
1
就可以监控ftp上传的文件了。非常方便。
虽然是个老的技术。但是通过golang,可以非常的方便的搭建一个ftp服务器。
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/82048257
博主地址是:http://blog.csdn.net/freewebsys
本帖子属于以下条目()
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.