mirror of https://github.com/Xhofe/alist
fix: copy folder between two storage (fix #1670)
parent
86a625cb40
commit
d9f0603271
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -338,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)
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ func (t *Task[K]) run() {
|
|||
t.state = ERRORED
|
||||
} else {
|
||||
t.state = SUCCEEDED
|
||||
t.SetProgress(100)
|
||||
if t.callback != nil {
|
||||
t.callback(t)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
@ -10,6 +13,64 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 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 = CreateNestedFile(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
|
||||
}
|
||||
|
||||
// Exists determine whether the file exists
|
||||
func Exists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
|
|
Loading…
Reference in New Issue