mirror of https://github.com/Xhofe/alist
feat(url-tree): implement the Put interface to support adding links directly to the UrlTree on the web side (#8312)
* feat(url-tree)支持PUT * feat(url-tree) UrlTree更新时,需要将路径和内容分割 #8303 * fix: stdpath.Join call Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Andy Hsu <i@nn.ci> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>pull/8376/head
parent
f0b1aeaf8d
commit
88abb323cb
|
@ -243,7 +243,25 @@ func (d *Urls) PutURL(ctx context.Context, dstDir model.Obj, name, url string) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Urls) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Urls) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
return errs.UploadNotSupported
|
if !d.Writable {
|
||||||
|
return errs.PermissionDenied
|
||||||
|
}
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
node := GetNodeFromRootByPath(d.root, dstDir.GetPath()) // parent
|
||||||
|
if node == nil {
|
||||||
|
return errs.ObjectNotFound
|
||||||
|
}
|
||||||
|
if node.isFile() {
|
||||||
|
return errs.NotFolder
|
||||||
|
}
|
||||||
|
file, err := parseFileLine(stream.GetName(), d.HeadSize)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
node.Children = append(node.Children, file)
|
||||||
|
d.updateStorage()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Urls) updateStorage() {
|
func (d *Urls) updateStorage() {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/stream"
|
||||||
"github.com/alist-org/alist/v3/pkg/generic_sync"
|
"github.com/alist-org/alist/v3/pkg/generic_sync"
|
||||||
"github.com/alist-org/alist/v3/pkg/singleflight"
|
"github.com/alist-org/alist/v3/pkg/singleflight"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
@ -517,6 +518,12 @@ func Put(ctx context.Context, storage driver.Driver, dstDirPath string, file mod
|
||||||
log.Errorf("failed to close file streamer, %v", err)
|
log.Errorf("failed to close file streamer, %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
// UrlTree PUT
|
||||||
|
if storage.GetStorage().Driver == "UrlTree" {
|
||||||
|
var link string
|
||||||
|
dstDirPath, link = urlTreeSplitLineFormPath(stdpath.Join(dstDirPath, file.GetName()))
|
||||||
|
file = &stream.FileStream{Obj: &model.Object{Name: link}}
|
||||||
|
}
|
||||||
// if file exist and size = 0, delete it
|
// if file exist and size = 0, delete it
|
||||||
dstDirPath = utils.FixAndCleanPath(dstDirPath)
|
dstDirPath = utils.FixAndCleanPath(dstDirPath)
|
||||||
dstPath := stdpath.Join(dstDirPath, file.GetName())
|
dstPath := stdpath.Join(dstDirPath, file.GetName())
|
||||||
|
|
|
@ -2,6 +2,7 @@ package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
|
stdpath "path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
@ -27,3 +28,30 @@ func GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath
|
||||||
actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, mountPath))
|
actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, mountPath))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// urlTreeSplitLineFormPath 分割path中分割真实路径和UrlTree定义字符串
|
||||||
|
func urlTreeSplitLineFormPath(path string) (pp string, file string) {
|
||||||
|
// url.PathUnescape 会移除 // ,手动加回去
|
||||||
|
path = strings.Replace(path, "https:/", "https://", 1)
|
||||||
|
path = strings.Replace(path, "http:/", "http://", 1)
|
||||||
|
if strings.Contains(path, ":https:/") || strings.Contains(path, ":http:/") {
|
||||||
|
// URL-Tree模式 /url_tree_drivr/file_name[:size[:time]]:https://example.com/file
|
||||||
|
fPath := strings.SplitN(path, ":", 2)[0]
|
||||||
|
pp, _ = stdpath.Split(fPath)
|
||||||
|
file = path[len(pp):]
|
||||||
|
} else if strings.Contains(path, "/https:/") || strings.Contains(path, "/http:/") {
|
||||||
|
// URL-Tree模式 /url_tree_drivr/https://example.com/file
|
||||||
|
index := strings.Index(path, "/http://")
|
||||||
|
if index == -1 {
|
||||||
|
index = strings.Index(path, "/https://")
|
||||||
|
}
|
||||||
|
pp = path[:index]
|
||||||
|
file = path[index+1:]
|
||||||
|
} else {
|
||||||
|
pp, file = stdpath.Split(path)
|
||||||
|
}
|
||||||
|
if pp == "" {
|
||||||
|
pp = "/"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue