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())
|
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||||
var err error
|
var err error
|
||||||
if srcObj.IsDir() {
|
if srcObj.IsDir() {
|
||||||
err = copyDir(srcPath, dstPath)
|
err = utils.CopyDir(srcPath, dstPath)
|
||||||
} else {
|
} else {
|
||||||
err = copyFile(srcPath, dstPath)
|
err = utils.CopyFile(srcPath, dstPath)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,67 +1 @@
|
||||||
package local
|
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/task"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var CopyTaskManager = task.NewTaskManager(3, func(tid *uint64) {
|
var CopyTaskManager = task.NewTaskManager(3, func(tid *uint64) {
|
||||||
|
@ -60,7 +61,7 @@ func copyBetween2Storages(t *task.Task[uint64], srcStorage, dstStorage driver.Dr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
srcObjPath := stdpath.Join(srcObjPath, obj.GetName())
|
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]{
|
CopyTaskManager.Submit(task.WithCancelCtx(&task.Task[uint64]{
|
||||||
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstObjPath),
|
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstObjPath),
|
||||||
Func: func(t *task.Task[uint64]) error {
|
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]{
|
CopyTaskManager.Submit(task.WithCancelCtx(&task.Task[uint64]{
|
||||||
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstDirPath),
|
Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjPath, dstStorage.GetStorage().MountPath, dstDirPath),
|
||||||
Func: func(t *task.Task[uint64]) error {
|
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
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -8,8 +9,11 @@ import (
|
||||||
stdpath "path"
|
stdpath "path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,7 +42,13 @@ func getFileStreamFromLink(file model.Obj, link *model.Link) (model.FileStreamer
|
||||||
if link.Data != nil {
|
if link.Data != nil {
|
||||||
rc = link.Data
|
rc = link.Data
|
||||||
} else if link.FilePath != nil {
|
} 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 {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to open file %s", *link.FilePath)
|
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)
|
err = storage.Put(ctx, parentDir, file, up)
|
||||||
log.Debugf("put file [%s] done", file.GetName())
|
log.Debugf("put file [%s] done", file.GetName())
|
||||||
if err == nil {
|
//if err == nil {
|
||||||
// set as complete
|
// //clear cache
|
||||||
up(100)
|
// key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
|
||||||
// clear cache
|
// listCache.Del(key)
|
||||||
//key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
|
//}
|
||||||
//listCache.Del(key)
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ func (t *Task[K]) run() {
|
||||||
t.state = ERRORED
|
t.state = ERRORED
|
||||||
} else {
|
} else {
|
||||||
t.state = SUCCEEDED
|
t.state = SUCCEEDED
|
||||||
|
t.SetProgress(100)
|
||||||
if t.callback != nil {
|
if t.callback != nil {
|
||||||
t.callback(t)
|
t.callback(t)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -10,6 +13,64 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
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
|
// Exists determine whether the file exists
|
||||||
func Exists(name string) bool {
|
func Exists(name string) bool {
|
||||||
if _, err := os.Stat(name); err != nil {
|
if _, err := os.Stat(name); err != nil {
|
||||||
|
|
Loading…
Reference in New Issue