mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2026-10-10 21:13:10 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3b213c398 | |||
| d9f0603271 | |||
| 86a625cb40 | |||
| f22232de5d | |||
| 7ad3748a46 | |||
| 66b2562d03 | |||
| b197322cd8 | |||
| 9e5ef974a7 | |||
| 08a001fbd1 | |||
| 54ae6dce0b | |||
| a90ef201c7 | |||
| 2de0da87fa | |||
| 53e08e75fe | |||
| 6b5236f52e | |||
| 78e34f0d9f |
@@ -10,5 +10,6 @@ LABEL MAINTAINER="i@nn.ci"
|
||||
VOLUME /opt/alist/data/
|
||||
WORKDIR /opt/alist/
|
||||
COPY --from=builder /app/bin/alist ./
|
||||
RUN apk add ca-certificates
|
||||
EXPOSE 5244
|
||||
CMD [ "./alist", "server", "--no-prefix" ]
|
||||
@@ -88,3 +88,12 @@ func init() {
|
||||
// is called directly, e.g.:
|
||||
// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
||||
// OutAlistInit 暴露用于外部启动server的函数
|
||||
func OutAlistInit() {
|
||||
var (
|
||||
cmd *cobra.Command
|
||||
args []string
|
||||
)
|
||||
serverCmd.Run(cmd, args)
|
||||
}
|
||||
|
||||
+10
-11
@@ -3,8 +3,6 @@ package _189pc
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -133,16 +131,17 @@ func (y *Yun189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs
|
||||
"User-Agent": []string{base.UserAgent},
|
||||
},
|
||||
}
|
||||
|
||||
// 获取链接有效时常
|
||||
strs := regexp.MustCompile(`(?i)expire[^=]*=([0-9]*)`).FindStringSubmatch(downloadUrl.URL)
|
||||
if len(strs) == 2 {
|
||||
timestamp, err := strconv.ParseInt(strs[1], 10, 64)
|
||||
if err == nil {
|
||||
expired := time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||
like.Expiration = &expired
|
||||
/*
|
||||
// 获取链接有效时常
|
||||
strs := regexp.MustCompile(`(?i)expire[^=]*=([0-9]*)`).FindStringSubmatch(downloadUrl.URL)
|
||||
if len(strs) == 2 {
|
||||
timestamp, err := strconv.ParseInt(strs[1], 10, 64)
|
||||
if err == nil {
|
||||
expired := time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||
like.Expiration = &expired
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return like, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -508,7 +508,6 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
||||
_ = tempFile.Close()
|
||||
_ = os.Remove(tempFile.Name())
|
||||
}()
|
||||
file.SetReadCloser(tempFile)
|
||||
|
||||
const DEFAULT int64 = 10485760
|
||||
count := int(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
|
||||
@@ -526,14 +525,16 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
||||
}
|
||||
|
||||
silceMd5.Reset()
|
||||
if _, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5), file, DEFAULT); err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
||||
if _, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5), tempFile, DEFAULT); err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
||||
return err
|
||||
}
|
||||
md5Byte := silceMd5.Sum(nil)
|
||||
silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Byte)))
|
||||
silceMd5Base64s = append(silceMd5Base64s, fmt.Sprint(i, "-", base64.StdEncoding.EncodeToString(md5Byte)))
|
||||
}
|
||||
file.GetReadCloser().(*os.File).Seek(0, io.SeekStart)
|
||||
if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
|
||||
sliceMd5Hex := fileMd5Hex
|
||||
@@ -594,7 +595,7 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
||||
SetContext(ctx).
|
||||
SetQueryParams(clientSuffix()).
|
||||
SetHeaders(ParseHttpHeader(uploadData.RequestHeader)).
|
||||
SetBody(io.LimitReader(file, DEFAULT)).
|
||||
SetBody(io.LimitReader(tempFile, DEFAULT)).
|
||||
Put(uploadData.RequestURL)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
_ "github.com/alist-org/alist/v3/drivers/189pc"
|
||||
_ "github.com/alist-org/alist/v3/drivers/aliyundrive"
|
||||
_ "github.com/alist-org/alist/v3/drivers/baidu_netdisk"
|
||||
_ "github.com/alist-org/alist/v3/drivers/baidu_photo"
|
||||
_ "github.com/alist-org/alist/v3/drivers/ftp"
|
||||
_ "github.com/alist-org/alist/v3/drivers/google_drive"
|
||||
_ "github.com/alist-org/alist/v3/drivers/local"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
package baiduphoto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
)
|
||||
|
||||
//Tid生成
|
||||
func getTid() string {
|
||||
return fmt.Sprintf("3%d%.0f", time.Now().Unix(), math.Floor(9000000*rand.Float64()+1000000))
|
||||
}
|
||||
|
||||
// 检查名称
|
||||
func checkName(name string) bool {
|
||||
return len(name) <= 20 && regexp.MustCompile("[\u4e00-\u9fa5A-Za-z0-9_-]").MatchString(name)
|
||||
}
|
||||
|
||||
func toTime(t int64) *time.Time {
|
||||
tm := time.Unix(t, 0)
|
||||
return &tm
|
||||
}
|
||||
|
||||
func fsidsFormat(ids ...string) string {
|
||||
var buf []string
|
||||
for _, id := range ids {
|
||||
e := splitID(id)
|
||||
buf = append(buf, fmt.Sprintf(`{"fsid":%s,"uk":%s}`, e[0], e[3]))
|
||||
}
|
||||
return fmt.Sprintf("[%s]", strings.Join(buf, ","))
|
||||
}
|
||||
|
||||
func fsidsFormatNotUk(ids ...string) string {
|
||||
var buf []string
|
||||
for _, id := range ids {
|
||||
buf = append(buf, fmt.Sprintf(`{"fsid":%s}`, splitID(id)[0]))
|
||||
}
|
||||
return fmt.Sprintf("[%s]", strings.Join(buf, ","))
|
||||
}
|
||||
|
||||
/*
|
||||
结构
|
||||
|
||||
{fsid} 文件
|
||||
|
||||
{album_id}|{tid} 相册
|
||||
|
||||
{fsid}|{album_id}|{tid}|{uk} 相册文件
|
||||
*/
|
||||
func splitID(id string) []string {
|
||||
return strings.SplitN(id, "|", 4)[:4]
|
||||
}
|
||||
|
||||
/*
|
||||
结构
|
||||
|
||||
{fsid} 文件
|
||||
|
||||
{album_id}|{tid} 相册
|
||||
|
||||
{fsid}|{album_id}|{tid}|{uk} 相册文件
|
||||
*/
|
||||
func joinID(ids ...interface{}) string {
|
||||
idsStr := make([]string, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
idsStr = append(idsStr, fmt.Sprint(id))
|
||||
}
|
||||
return strings.Join(idsStr, "|")
|
||||
}
|
||||
|
||||
func getFileName(path string) string {
|
||||
return path[strings.LastIndex(path, "/")+1:]
|
||||
}
|
||||
|
||||
// 相册
|
||||
func IsAlbum(obj model.Obj) bool {
|
||||
return obj.IsDir() && obj.GetPath() == "album"
|
||||
}
|
||||
|
||||
// 根目录
|
||||
func IsRoot(obj model.Obj) bool {
|
||||
return obj.IsDir() && obj.GetPath() == "" && obj.GetID() == ""
|
||||
}
|
||||
|
||||
// 以相册为根目录
|
||||
func IsAlbumRoot(obj model.Obj) bool {
|
||||
return obj.IsDir() && obj.GetPath() == "" && obj.GetID() != ""
|
||||
}
|
||||
|
||||
// 根文件
|
||||
func IsFile(obj model.Obj) bool {
|
||||
return !obj.IsDir() && obj.GetPath() == "file"
|
||||
}
|
||||
|
||||
// 相册文件
|
||||
func IsAlbumFile(obj model.Obj) bool {
|
||||
return !obj.IsDir() && obj.GetPath() == "albumfile"
|
||||
}
|
||||
|
||||
func MustString(str string, err error) string {
|
||||
return str
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package baiduphoto
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
RefreshToken string `json:"refresh_token" required:"true"`
|
||||
ShowType string `json:"show_type" type:"select" options:"root,root_only_album,root_only_file" default:"root"`
|
||||
AlbumID string `json:"album_id"`
|
||||
//AlbumPassword string `json:"album_password"`
|
||||
ClientID string `json:"client_id" required:"true" default:"iYCeC9g08h5vuP9UqvPHKKSVrKFXGa1v"`
|
||||
ClientSecret string `json:"client_secret" required:"true" default:"jXiFMOPVPCWlO2M5CwWQzffpNPaGTRBG"`
|
||||
}
|
||||
|
||||
func (a Addition) GetRootId() string {
|
||||
return a.AlbumID
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "BaiduPhoto",
|
||||
LocalSort: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
return &BaiduPhoto{}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package baiduphoto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TokenErrResp struct {
|
||||
ErrorDescription string `json:"error_description"`
|
||||
ErrorMsg string `json:"error"`
|
||||
}
|
||||
|
||||
func (e *TokenErrResp) Error() string {
|
||||
return fmt.Sprint(e.ErrorMsg, " : ", e.ErrorDescription)
|
||||
}
|
||||
|
||||
type Erron struct {
|
||||
Errno int `json:"errno"`
|
||||
RequestID int `json:"request_id"`
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
HasMore int `json:"has_more"`
|
||||
Cursor string `json:"cursor"`
|
||||
}
|
||||
|
||||
func (p Page) HasNextPage() bool {
|
||||
return p.HasMore == 1
|
||||
}
|
||||
|
||||
type (
|
||||
FileListResp struct {
|
||||
Page
|
||||
List []File `json:"list"`
|
||||
}
|
||||
|
||||
File struct {
|
||||
Fsid int64 `json:"fsid"` // 文件ID
|
||||
Path string `json:"path"` // 文件路径
|
||||
Size int64 `json:"size"`
|
||||
Ctime int64 `json:"ctime"` // 创建时间 s
|
||||
Mtime int64 `json:"mtime"` // 修改时间 s
|
||||
Thumburl []string `json:"thumburl"`
|
||||
|
||||
parseTime *time.Time
|
||||
}
|
||||
)
|
||||
|
||||
func (c *File) GetSize() int64 { return c.Size }
|
||||
func (c *File) GetName() string { return getFileName(c.Path) }
|
||||
func (c *File) ModTime() time.Time {
|
||||
if c.parseTime == nil {
|
||||
c.parseTime = toTime(c.Mtime)
|
||||
}
|
||||
return *c.parseTime
|
||||
}
|
||||
func (c *File) IsDir() bool { return false }
|
||||
func (c *File) GetID() string { return joinID(c.Fsid) }
|
||||
func (c *File) GetPath() string { return "file" }
|
||||
func (c *File) Thumb() string {
|
||||
if len(c.Thumburl) > 0 {
|
||||
return c.Thumburl[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
/*相册部分*/
|
||||
type (
|
||||
AlbumListResp struct {
|
||||
Page
|
||||
List []Album `json:"list"`
|
||||
Reset int64 `json:"reset"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
Album struct {
|
||||
AlbumID string `json:"album_id"`
|
||||
Tid int64 `json:"tid"`
|
||||
Title string `json:"title"`
|
||||
JoinTime int64 `json:"join_time"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
Mtime int64 `json:"mtime"`
|
||||
|
||||
parseTime *time.Time
|
||||
}
|
||||
|
||||
AlbumFileListResp struct {
|
||||
Page
|
||||
List []AlbumFile `json:"list"`
|
||||
Reset int64 `json:"reset"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
}
|
||||
|
||||
AlbumFile struct {
|
||||
File
|
||||
AlbumID string `json:"album_id"`
|
||||
Tid int64 `json:"tid"`
|
||||
Uk int64 `json:"uk"`
|
||||
}
|
||||
)
|
||||
|
||||
func (a *Album) GetSize() int64 { return 0 }
|
||||
func (a *Album) GetName() string { return fmt.Sprint(a.Title) }
|
||||
func (a *Album) ModTime() time.Time {
|
||||
if a.parseTime == nil {
|
||||
a.parseTime = toTime(a.Mtime)
|
||||
}
|
||||
return *a.parseTime
|
||||
}
|
||||
func (a *Album) IsDir() bool { return true }
|
||||
func (a *Album) GetID() string { return joinID(a.AlbumID, a.Tid) }
|
||||
func (a *Album) GetPath() string { return "album" }
|
||||
|
||||
func (af *AlbumFile) GetID() string { return joinID(af.Fsid, af.AlbumID, af.Tid, af.Uk) }
|
||||
func (c *AlbumFile) GetPath() string { return "albumfile" }
|
||||
|
||||
type (
|
||||
CopyFileResp struct {
|
||||
List []CopyFile `json:"list"`
|
||||
}
|
||||
CopyFile struct {
|
||||
FromFsid int64 `json:"from_fsid"` // 源ID
|
||||
Fsid int64 `json:"fsid"` // 目标ID
|
||||
Path string `json:"path"`
|
||||
ShootTime int `json:"shoot_time"`
|
||||
}
|
||||
)
|
||||
|
||||
/*上传部分*/
|
||||
type (
|
||||
UploadFile struct {
|
||||
FsID int64 `json:"fs_id"`
|
||||
Size int64 `json:"size"`
|
||||
Md5 string `json:"md5"`
|
||||
ServerFilename string `json:"server_filename"`
|
||||
Path string `json:"path"`
|
||||
Ctime int `json:"ctime"`
|
||||
Mtime int `json:"mtime"`
|
||||
Isdir int `json:"isdir"`
|
||||
Category int `json:"category"`
|
||||
ServerMd5 string `json:"server_md5"`
|
||||
ShootTime int `json:"shoot_time"`
|
||||
}
|
||||
|
||||
CreateFileResp struct {
|
||||
Data UploadFile `json:"data"`
|
||||
}
|
||||
|
||||
PrecreateResp struct {
|
||||
ReturnType int `json:"return_type"` //存在返回2 不存在返回1 已经保存3
|
||||
//存在返回
|
||||
CreateFileResp
|
||||
|
||||
//不存在返回
|
||||
Path string `json:"path"`
|
||||
UploadID string `json:"uploadid"`
|
||||
Blocklist []int64 `json:"block_list"`
|
||||
}
|
||||
)
|
||||
|
||||
type InviteResp struct {
|
||||
Pdata struct {
|
||||
// 邀请码
|
||||
InviteCode string `json:"invite_code"`
|
||||
// 有效时间
|
||||
ExpireTime int `json:"expire_time"`
|
||||
ShareID string `json:"share_id"`
|
||||
} `json:"pdata"`
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -175,9 +175,9 @@ func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||
var err error
|
||||
if srcObj.IsDir() {
|
||||
err = copyDir(srcPath, dstPath)
|
||||
err = utils.CopyDir(srcPath, dstPath)
|
||||
} else {
|
||||
err = copyFile(srcPath, dstPath)
|
||||
err = utils.CopyFile(srcPath, dstPath)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,67 +1 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// copyFile File copies a single file from src to dst
|
||||
func copyFile(src, dst string) error {
|
||||
var err error
|
||||
var srcfd *os.File
|
||||
var dstfd *os.File
|
||||
var srcinfo os.FileInfo
|
||||
|
||||
if srcfd, err = os.Open(src); err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcfd.Close()
|
||||
|
||||
if dstfd, err = os.Create(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstfd.Close()
|
||||
|
||||
if _, err = io.Copy(dstfd, srcfd); err != nil {
|
||||
return err
|
||||
}
|
||||
if srcinfo, err = os.Stat(src); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chmod(dst, srcinfo.Mode())
|
||||
}
|
||||
|
||||
// copyDir Dir copies a whole directory recursively
|
||||
func copyDir(src string, dst string) error {
|
||||
var err error
|
||||
var fds []os.FileInfo
|
||||
var srcinfo os.FileInfo
|
||||
|
||||
if srcinfo, err = os.Stat(src); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
if fds, err = ioutil.ReadDir(src); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fd := range fds {
|
||||
srcfp := path.Join(src, fd.Name())
|
||||
dstfp := path.Join(dst, fd.Name())
|
||||
|
||||
if fd.IsDir() {
|
||||
if err = copyDir(srcfp, dstfp); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
if err = copyFile(srcfp, dstfp); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
@@ -90,6 +91,9 @@ func (d *Quark) MakeDir(ctx context.Context, parentDir model.Obj, dirName string
|
||||
_, err := d.request("/file", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
if err == nil {
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
@@ -255,14 +252,16 @@ func (xc *XunLeiCommon) Link(ctx context.Context, file model.Obj, args model.Lin
|
||||
},
|
||||
}
|
||||
|
||||
strs := regexp.MustCompile(`e=([0-9]*)`).FindStringSubmatch(lFile.WebContentLink)
|
||||
if len(strs) == 2 {
|
||||
timestamp, err := strconv.ParseInt(strs[1], 10, 64)
|
||||
if err == nil {
|
||||
expired := time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||
link.Expiration = &expired
|
||||
/*
|
||||
strs := regexp.MustCompile(`e=([0-9]*)`).FindStringSubmatch(lFile.WebContentLink)
|
||||
if len(strs) == 2 {
|
||||
timestamp, err := strconv.ParseInt(strs[1], 10, 64)
|
||||
if err == nil {
|
||||
expired := time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||
link.Expiration = &expired
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return link, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
func InitAria2() {
|
||||
go func() {
|
||||
_, err := aria2.InitClient(2)
|
||||
utils.Log.Errorf("failed to init aria2 client: %+v", err)
|
||||
if err != nil {
|
||||
utils.Log.Errorf("failed to init aria2 client: %+v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -53,6 +53,9 @@ func InitDB() {
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s",
|
||||
database.User, database.Password, database.Host, database.Port, database.Name, database.SSLMode)
|
||||
dB, err = gorm.Open(mysql.Open(dsn), gormConfig)
|
||||
if err == nil {
|
||||
dB = dB.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4")
|
||||
}
|
||||
}
|
||||
case "postgres":
|
||||
{
|
||||
|
||||
+2
-2
@@ -7,10 +7,10 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var db gorm.DB
|
||||
var db *gorm.DB
|
||||
|
||||
func Init(d *gorm.DB) {
|
||||
db = *d
|
||||
db = d
|
||||
err := db.AutoMigrate(new(model.Storage), new(model.User), new(model.Meta), new(model.SettingItem))
|
||||
if err != nil {
|
||||
log.Fatalf("failed migrate database: %s", err.Error())
|
||||
|
||||
+5
-2
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/alist-org/alist/v3/pkg/task"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var CopyTaskManager = task.NewTaskManager(3, func(tid *uint64) {
|
||||
@@ -60,7 +61,7 @@ func copyBetween2Storages(t *task.Task[uint64], srcStorage, dstStorage driver.Dr
|
||||
return nil
|
||||
}
|
||||
srcObjPath := stdpath.Join(srcObjPath, obj.GetName())
|
||||
dstObjPath := stdpath.Join(dstDirPath, obj.GetName())
|
||||
dstObjPath := stdpath.Join(dstDirPath, srcObj.GetName())
|
||||
CopyTaskManager.Submit(task.WithCancelCtx(&task.Task[uint64]{
|
||||
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstObjPath),
|
||||
Func: func(t *task.Task[uint64]) error {
|
||||
@@ -72,7 +73,9 @@ func copyBetween2Storages(t *task.Task[uint64], srcStorage, dstStorage driver.Dr
|
||||
CopyTaskManager.Submit(task.WithCancelCtx(&task.Task[uint64]{
|
||||
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstDirPath),
|
||||
Func: func(t *task.Task[uint64]) error {
|
||||
return copyFileBetween2Storages(t, srcStorage, dstStorage, srcObjPath, dstDirPath)
|
||||
err := copyFileBetween2Storages(t, srcStorage, dstStorage, srcObjPath, dstDirPath)
|
||||
log.Debugf("copy file between storages: %+v", err)
|
||||
return err
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
+11
-1
@@ -1,6 +1,7 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
@@ -8,8 +9,11 @@ import (
|
||||
stdpath "path"
|
||||
"strings"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/conf"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -38,7 +42,13 @@ func getFileStreamFromLink(file model.Obj, link *model.Link) (model.FileStreamer
|
||||
if link.Data != nil {
|
||||
rc = link.Data
|
||||
} else if link.FilePath != nil {
|
||||
f, err := os.Open(*link.FilePath)
|
||||
// copy a new temp, because will be deleted after upload
|
||||
newFilePath := stdpath.Join(conf.Conf.TempDir, fmt.Sprintf("%s-%s", uuid.NewString(), file.GetName()))
|
||||
err := utils.CopyFile(*link.FilePath, newFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := os.Open(newFilePath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to open file %s", *link.FilePath)
|
||||
}
|
||||
|
||||
+38
-10
@@ -27,6 +27,10 @@ func ClearCache(storage driver.Driver, path string) {
|
||||
listCache.Del(key)
|
||||
}
|
||||
|
||||
func Key(storage driver.Driver, path string) string {
|
||||
return stdpath.Join(storage.GetStorage().MountPath, utils.StandardizePath(path))
|
||||
}
|
||||
|
||||
// List files in storage, not contains virtual file
|
||||
func List(ctx context.Context, storage driver.Driver, path string, args model.ListArgs, refresh ...bool) ([]model.Obj, error) {
|
||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
||||
@@ -46,7 +50,7 @@ func List(ctx context.Context, storage driver.Driver, path string, args model.Li
|
||||
objs, err := storage.List(ctx, dir, args)
|
||||
return objs, errors.WithStack(err)
|
||||
}
|
||||
key := stdpath.Join(storage.GetStorage().MountPath, path)
|
||||
key := Key(storage, path)
|
||||
if len(refresh) == 0 || !refresh[0] {
|
||||
if files, ok := listCache.Get(key); ok {
|
||||
return files, nil
|
||||
@@ -181,6 +185,7 @@ func MakeDir(ctx context.Context, storage driver.Driver, path string) error {
|
||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
||||
}
|
||||
path = utils.StandardizePath(path)
|
||||
// check if dir exists
|
||||
f, err := Get(ctx, storage, path)
|
||||
if err != nil {
|
||||
@@ -195,7 +200,11 @@ func MakeDir(ctx context.Context, storage driver.Driver, path string) error {
|
||||
if err != nil {
|
||||
return errors.WithMessagef(err, "failed to get parent dir [%s]", parentPath)
|
||||
}
|
||||
return errors.WithStack(storage.MakeDir(ctx, parentDir, dirName))
|
||||
err = storage.MakeDir(ctx, parentDir, dirName)
|
||||
if err == nil {
|
||||
ClearCache(storage, parentPath)
|
||||
}
|
||||
return errors.WithStack(err)
|
||||
} else {
|
||||
return errors.WithMessage(err, "failed to check if dir exists")
|
||||
}
|
||||
@@ -261,7 +270,28 @@ func Remove(ctx context.Context, storage driver.Driver, path string) error {
|
||||
}
|
||||
return errors.WithMessage(err, "failed to get object")
|
||||
}
|
||||
return errors.WithStack(storage.Remove(ctx, obj))
|
||||
err = storage.Remove(ctx, obj)
|
||||
if err == nil {
|
||||
key := Key(storage, stdpath.Dir(path))
|
||||
if objs, ok := listCache.Get(key); ok {
|
||||
j := -1
|
||||
for i, m := range objs {
|
||||
if m.GetName() == obj.GetName() {
|
||||
j = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if j >= 0 && j < len(objs) {
|
||||
objs = append(objs[:j], objs[j+1:]...)
|
||||
listCache.Set(key, objs)
|
||||
} else {
|
||||
log.Debugf("not found obj")
|
||||
}
|
||||
} else {
|
||||
log.Debugf("not found parent cache")
|
||||
}
|
||||
}
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
func Put(ctx context.Context, storage driver.Driver, dstDirPath string, file model.FileStreamer, up driver.UpdateProgress) error {
|
||||
@@ -308,12 +338,10 @@ func Put(ctx context.Context, storage driver.Driver, dstDirPath string, file mod
|
||||
}
|
||||
err = storage.Put(ctx, parentDir, file, up)
|
||||
log.Debugf("put file [%s] done", file.GetName())
|
||||
if err == nil {
|
||||
// set as complete
|
||||
up(100)
|
||||
// clear cache
|
||||
key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
|
||||
listCache.Del(key)
|
||||
}
|
||||
//if err == nil {
|
||||
// //clear cache
|
||||
// key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
|
||||
// listCache.Del(key)
|
||||
//}
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user