alist/drivers/local/driver.go

238 lines
5.5 KiB
Go
Raw Normal View History

2022-06-06 22:06:33 +08:00
package local
2022-06-07 18:13:55 +08:00
import (
2022-08-11 20:32:17 +08:00
"bytes"
2022-06-07 18:13:55 +08:00
"context"
2022-08-31 20:58:57 +08:00
"errors"
"fmt"
2022-08-11 20:32:17 +08:00
"io"
2022-06-23 17:06:07 +08:00
"io/ioutil"
2022-08-11 20:32:17 +08:00
"net/http"
2022-06-23 17:06:07 +08:00
"os"
2022-08-11 20:32:17 +08:00
stdpath "path"
2022-06-23 17:06:07 +08:00
"path/filepath"
2022-08-11 20:32:17 +08:00
"strconv"
2022-06-23 17:06:07 +08:00
"strings"
2022-06-14 19:44:25 +08:00
2022-08-11 20:32:17 +08:00
"github.com/alist-org/alist/v3/internal/conf"
2022-06-07 18:13:55 +08:00
"github.com/alist-org/alist/v3/internal/driver"
2023-01-16 19:55:43 +08:00
"github.com/alist-org/alist/v3/internal/errs"
2022-06-07 18:13:55 +08:00
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/sign"
2022-06-07 18:13:55 +08:00
"github.com/alist-org/alist/v3/pkg/utils"
2022-08-11 20:32:17 +08:00
"github.com/alist-org/alist/v3/server/common"
"github.com/disintegration/imaging"
_ "golang.org/x/image/webp"
2022-06-07 18:13:55 +08:00
)
2022-07-19 17:11:53 +08:00
type Local struct {
2022-07-10 14:45:39 +08:00
model.Storage
2022-06-07 18:13:55 +08:00
Addition
}
2022-07-19 17:11:53 +08:00
func (d *Local) Config() driver.Config {
2022-06-07 18:13:55 +08:00
return config
}
func (d *Local) Init(ctx context.Context) error {
if d.MkdirPerm == 0 {
d.MkdirPerm = 777
}
2022-09-04 13:07:53 +08:00
if !utils.Exists(d.GetRootPath()) {
return fmt.Errorf("root folder %s not exists", d.GetRootPath())
}
if !filepath.IsAbs(d.GetRootPath()) {
abs, err := filepath.Abs(d.GetRootPath())
if err != nil {
return err
2022-06-27 20:37:05 +08:00
}
d.Addition.RootFolderPath = abs
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Drop(ctx context.Context) error {
2022-06-07 22:02:41 +08:00
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) GetAddition() driver.Additional {
return &d.Addition
2022-06-07 18:13:55 +08:00
}
2022-08-11 20:32:17 +08:00
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
2022-09-02 22:46:31 +08:00
fullPath := dir.GetPath()
2022-06-23 17:06:07 +08:00
rawFiles, err := ioutil.ReadDir(fullPath)
if err != nil {
2022-08-31 20:58:57 +08:00
return nil, err
2022-06-23 17:06:07 +08:00
}
var files []model.Obj
for _, f := range rawFiles {
if !d.ShowHidden && strings.HasPrefix(f.Name(), ".") {
2022-06-23 17:06:07 +08:00
continue
}
2022-08-11 20:32:17 +08:00
thumb := ""
if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
2022-08-11 20:32:17 +08:00
thumb = utils.EncodePath(thumb, true)
thumb += "?type=thumb&sign=" + sign.Sign(stdpath.Join(args.ReqPath, f.Name()))
2022-08-11 20:32:17 +08:00
}
isFolder := f.IsDir() || isSymlinkDir(f, fullPath)
var size int64
if !isFolder {
size = f.Size()
}
2022-09-02 18:24:14 +08:00
file := model.ObjThumb{
2022-08-11 20:32:17 +08:00
Object: model.Object{
Path: filepath.Join(dir.GetPath(), f.Name()),
2022-08-11 20:32:17 +08:00
Name: f.Name(),
Modified: f.ModTime(),
Size: size,
IsFolder: isFolder,
2022-08-11 20:32:17 +08:00
},
Thumbnail: model.Thumbnail{
Thumbnail: thumb,
},
2022-06-23 17:06:07 +08:00
}
files = append(files, &file)
}
return files, nil
2022-06-07 18:13:55 +08:00
}
2023-01-16 19:55:43 +08:00
func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
path = filepath.Join(d.GetRootPath(), path)
f, err := os.Stat(path)
if err != nil {
if strings.Contains(err.Error(), "cannot find the file") {
return nil, errs.ObjectNotFound
}
return nil, err
}
isFolder := f.IsDir() || isSymlinkDir(f, path)
size := f.Size()
if isFolder {
size = 0
}
file := model.Object{
Path: path,
Name: f.Name(),
Modified: f.ModTime(),
Size: size,
IsFolder: isFolder,
}
return &file, nil
}
2022-07-19 17:11:53 +08:00
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
2022-09-02 22:46:31 +08:00
fullPath := file.GetPath()
2022-08-11 20:32:17 +08:00
var link model.Link
if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
imgData, err := ioutil.ReadFile(fullPath)
if err != nil {
return nil, err
}
srcBuf := bytes.NewBuffer(imgData)
image, err := imaging.Decode(srcBuf)
if err != nil {
return nil, err
}
thumbImg := imaging.Resize(image, 144, 0, imaging.Lanczos)
var buf bytes.Buffer
err = imaging.Encode(&buf, thumbImg, imaging.PNG)
if err != nil {
return nil, err
}
size := buf.Len()
link.Data = io.NopCloser(&buf)
link.Header = http.Header{
"Content-Length": []string{strconv.Itoa(size)},
}
} else {
link.FilePath = &fullPath
2022-06-23 17:06:07 +08:00
}
return &link, nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
2022-09-02 22:46:31 +08:00
fullPath := filepath.Join(parentDir.GetPath(), dirName)
err := os.MkdirAll(fullPath, os.FileMode(d.MkdirPerm))
2022-06-23 17:06:07 +08:00
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 22:02:41 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
2022-09-02 22:46:31 +08:00
srcPath := srcObj.GetPath()
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
if utils.IsSubPath(srcPath, dstPath) {
return fmt.Errorf("the destination folder is a subfolder of the source folder")
}
2022-06-23 17:06:07 +08:00
err := os.Rename(srcPath, dstPath)
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
2022-09-02 22:46:31 +08:00
srcPath := srcObj.GetPath()
2022-06-23 17:06:07 +08:00
dstPath := filepath.Join(filepath.Dir(srcPath), newName)
err := os.Rename(srcPath, dstPath)
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
2022-09-02 22:46:31 +08:00
srcPath := srcObj.GetPath()
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
if utils.IsSubPath(srcPath, dstPath) {
return fmt.Errorf("the destination folder is a subfolder of the source folder")
}
2022-06-23 17:06:07 +08:00
var err error
if srcObj.IsDir() {
err = utils.CopyDir(srcPath, dstPath)
2022-06-23 17:06:07 +08:00
} else {
err = utils.CopyFile(srcPath, dstPath)
2022-06-23 17:06:07 +08:00
}
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Remove(ctx context.Context, obj model.Obj) error {
2022-06-23 17:06:07 +08:00
var err error
if obj.IsDir() {
2022-09-02 22:46:31 +08:00
err = os.RemoveAll(obj.GetPath())
2022-06-23 17:06:07 +08:00
} else {
2022-09-02 22:46:31 +08:00
err = os.Remove(obj.GetPath())
2022-06-23 17:06:07 +08:00
}
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
func (d *Local) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
2022-09-02 22:46:31 +08:00
fullPath := filepath.Join(dstDir.GetPath(), stream.GetName())
2022-06-23 17:06:07 +08:00
out, err := os.Create(fullPath)
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
defer func() {
_ = out.Close()
2022-06-25 15:14:03 +08:00
if errors.Is(err, context.Canceled) {
_ = os.Remove(fullPath)
}
2022-06-23 17:06:07 +08:00
}()
2022-08-31 22:41:27 +08:00
err = utils.CopyWithCtx(ctx, out, stream, stream.GetSize(), up)
2022-06-23 17:06:07 +08:00
if err != nil {
2022-08-31 20:58:57 +08:00
return err
2022-06-23 17:06:07 +08:00
}
return nil
2022-06-07 18:13:55 +08:00
}
2022-07-19 17:11:53 +08:00
var _ driver.Driver = (*Local)(nil)