Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/ftp/driver.go
1987 views
1
package ftp
2
3
import (
4
"context"
5
stdpath "path"
6
7
"github.com/alist-org/alist/v3/internal/driver"
8
"github.com/alist-org/alist/v3/internal/errs"
9
"github.com/alist-org/alist/v3/internal/model"
10
"github.com/jlaffaye/ftp"
11
)
12
13
type FTP struct {
14
model.Storage
15
Addition
16
conn *ftp.ServerConn
17
}
18
19
func (d *FTP) Config() driver.Config {
20
return config
21
}
22
23
func (d *FTP) GetAddition() driver.Additional {
24
return &d.Addition
25
}
26
27
func (d *FTP) Init(ctx context.Context) error {
28
return d.login()
29
}
30
31
func (d *FTP) Drop(ctx context.Context) error {
32
if d.conn != nil {
33
_ = d.conn.Logout()
34
}
35
return nil
36
}
37
38
func (d *FTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
39
if err := d.login(); err != nil {
40
return nil, err
41
}
42
entries, err := d.conn.List(encode(dir.GetPath(), d.Encoding))
43
if err != nil {
44
return nil, err
45
}
46
res := make([]model.Obj, 0)
47
for _, entry := range entries {
48
if entry.Name == "." || entry.Name == ".." {
49
continue
50
}
51
f := model.Object{
52
Name: decode(entry.Name, d.Encoding),
53
Size: int64(entry.Size),
54
Modified: entry.Time,
55
IsFolder: entry.Type == ftp.EntryTypeFolder,
56
}
57
res = append(res, &f)
58
}
59
return res, nil
60
}
61
62
func (d *FTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
63
if err := d.login(); err != nil {
64
return nil, err
65
}
66
67
r := NewFileReader(d.conn, encode(file.GetPath(), d.Encoding), file.GetSize())
68
link := &model.Link{
69
MFile: r,
70
}
71
return link, nil
72
}
73
74
func (d *FTP) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
75
if err := d.login(); err != nil {
76
return err
77
}
78
return d.conn.MakeDir(encode(stdpath.Join(parentDir.GetPath(), dirName), d.Encoding))
79
}
80
81
func (d *FTP) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
82
if err := d.login(); err != nil {
83
return err
84
}
85
return d.conn.Rename(
86
encode(srcObj.GetPath(), d.Encoding),
87
encode(stdpath.Join(dstDir.GetPath(), srcObj.GetName()), d.Encoding),
88
)
89
}
90
91
func (d *FTP) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
92
if err := d.login(); err != nil {
93
return err
94
}
95
return d.conn.Rename(
96
encode(srcObj.GetPath(), d.Encoding),
97
encode(stdpath.Join(stdpath.Dir(srcObj.GetPath()), newName), d.Encoding),
98
)
99
}
100
101
func (d *FTP) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
102
return errs.NotSupport
103
}
104
105
func (d *FTP) Remove(ctx context.Context, obj model.Obj) error {
106
if err := d.login(); err != nil {
107
return err
108
}
109
path := encode(obj.GetPath(), d.Encoding)
110
if obj.IsDir() {
111
return d.conn.RemoveDirRecur(path)
112
} else {
113
return d.conn.Delete(path)
114
}
115
}
116
117
func (d *FTP) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {
118
if err := d.login(); err != nil {
119
return err
120
}
121
path := stdpath.Join(dstDir.GetPath(), s.GetName())
122
return d.conn.Stor(encode(path, d.Encoding), driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
123
Reader: s,
124
UpdateProgress: up,
125
}))
126
}
127
128
var _ driver.Driver = (*FTP)(nil)
129
130