fix: copy folder between two storage (fix #1670)

pull/1831/head
Noah Hsu 2022-09-15 17:58:32 +08:00
parent 86a625cb40
commit d9f0603271
7 changed files with 85 additions and 78 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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
}, },
})) }))
} }

View File

@ -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)
} }

View File

@ -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)
// clear cache
// key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath) // key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
// listCache.Del(key) // listCache.Del(key)
} //}
return errors.WithStack(err) return errors.WithStack(err)
} }

View File

@ -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)
} }

View File

@ -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 {