mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 23:21:00 +08:00
115 lines
3.0 KiB
Go
115 lines
3.0 KiB
Go
package storage
|
|
|
|
import (
|
|
"io/fs"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"polaris/log"
|
|
"polaris/pkg/gowebdav"
|
|
"polaris/pkg/utils"
|
|
|
|
"github.com/gabriel-vasile/mimetype"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type WebdavStorage struct {
|
|
fs *gowebdav.Client
|
|
dir string
|
|
changeMediaHash bool
|
|
}
|
|
|
|
func NewWebdavStorage(url, user, password, path string, changeMediaHash bool) (*WebdavStorage, error) {
|
|
c := gowebdav.NewClient(url, user, password)
|
|
if err := c.Connect(); err != nil {
|
|
return nil, errors.Wrap(err, "connect webdav")
|
|
}
|
|
return &WebdavStorage{
|
|
fs: c,
|
|
dir: path,
|
|
}, nil
|
|
}
|
|
|
|
func (w *WebdavStorage) Copy(local, remoteDir string) error {
|
|
remoteBase := filepath.Join(w.dir, remoteDir, filepath.Base(local))
|
|
info, err := os.Stat(local)
|
|
if err != nil {
|
|
return errors.Wrap(err, "read source dir")
|
|
}
|
|
if info.IsDir() { //如果是路径,则只移动路径里面的文件,不管当前路径, 行为类似 move dirname/* target_dir/
|
|
remoteBase = filepath.Join(w.dir, remoteDir)
|
|
}
|
|
|
|
//log.Infof("remove all content in %s", remoteBase)
|
|
//w.fs.RemoveAll(remoteBase)
|
|
err = filepath.Walk(local, func(path string, info fs.FileInfo, err error) error {
|
|
if err != nil {
|
|
return errors.Wrapf(err, "read file %v", path)
|
|
}
|
|
|
|
rel, err := filepath.Rel(local, path)
|
|
if err != nil {
|
|
return errors.Wrap(err, "path relation")
|
|
}
|
|
remoteName := filepath.Join(remoteBase, rel)
|
|
|
|
if info.IsDir() {
|
|
log.Infof("skip dir %v, webdav will mkdir automatically", info.Name())
|
|
|
|
// if err := w.fs.Mkdir(remoteName, 0666); err != nil {
|
|
// return errors.Wrapf(err, "mkdir %v", remoteName)
|
|
// }
|
|
|
|
} else { //is file
|
|
if w.changeMediaHash {
|
|
if err := utils.ChangeFileHash(path); err != nil {
|
|
log.Errorf("change file %v hash error: %v", path, err)
|
|
}
|
|
}
|
|
if f, err := os.OpenFile(path, os.O_RDONLY, 0666); err != nil {
|
|
return errors.Wrapf(err, "read file %v", path)
|
|
} else { //open success
|
|
defer f.Close()
|
|
mtype, err := mimetype.DetectFile(path)
|
|
if err != nil {
|
|
return errors.Wrap(err, "mime type error")
|
|
}
|
|
|
|
callback := func(r *http.Request) {
|
|
r.Header.Set("Content-Type", mtype.String())
|
|
r.ContentLength = info.Size()
|
|
}
|
|
|
|
if err := w.fs.WriteStream(remoteName, f, 0666, callback); err != nil {
|
|
return errors.Wrap(err, "transmitting data error")
|
|
}
|
|
}
|
|
}
|
|
log.Infof("file copy complete: %v", remoteName)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return errors.Wrap(err, "move file error")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *WebdavStorage) Move(local, remoteDir string) error {
|
|
if err := w.Copy(local, remoteDir); err != nil {
|
|
return err
|
|
}
|
|
return os.RemoveAll(local)
|
|
}
|
|
|
|
func (w *WebdavStorage) ReadDir(dir string) ([]fs.FileInfo, error) {
|
|
return w.fs.ReadDir(filepath.Join(w.dir, dir))
|
|
}
|
|
|
|
func (w *WebdavStorage) ReadFile(name string) ([]byte, error) {
|
|
return w.fs.Read(filepath.Join(w.dir, name))
|
|
}
|
|
|
|
func (w *WebdavStorage) WriteFile(name string, data []byte) error {
|
|
return w.fs.Write(filepath.Join(w.dir, name), data, os.ModePerm)
|
|
}
|