mirror of https://github.com/Xhofe/alist
fix(ipfs): fix problems (#8252)
* fix: 🐛 (ipfs): fix the list error caused by not proper join path function
使用更加规范的路径拼接,修复了有中文或符号的路径无法正常访问的问题
* refactor: 命名规范
* 删除多余的条件判断
* fix: 使用withresult方法重构代码,添加get方法,提高性能
* fix: 允许get方法获取目录
去除多余的判断
* fix: 允许copy,rename,move进行覆写
* fix: 修复move方法导致的目录被删除
* refactor: 整理关于返回Path的代码
* fix: 修复由于get方法导致的ipfs路径无法访问
* fix: 修复path处理错误的get方法
修复get方法,删除意外加入的目录
* fix: fix path join
use path join instead of filepath join to avoid os problem
* fix: rm filepath ref
---------
Co-authored-by: Andy Hsu <i@nn.ci>
pull/8357/head
parent
ddffacf07b
commit
a4bfbf8a83
|
@ -4,8 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"path"
|
||||
|
||||
shell "github.com/ipfs/go-ipfs-api"
|
||||
|
||||
|
@ -43,78 +42,115 @@ func (d *IPFS) Drop(ctx context.Context) error {
|
|||
}
|
||||
|
||||
func (d *IPFS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
path := dir.GetPath()
|
||||
switch d.Mode {
|
||||
case "ipfs":
|
||||
path, _ = url.JoinPath("/ipfs", path)
|
||||
case "ipns":
|
||||
path, _ = url.JoinPath("/ipns", path)
|
||||
case "mfs":
|
||||
fileStat, err := d.sh.FilesStat(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var ipfsPath string
|
||||
cid := dir.GetID()
|
||||
if cid != "" {
|
||||
ipfsPath = path.Join("/ipfs", cid)
|
||||
} else {
|
||||
// 可能出现ipns dns解析失败的情况,需要重复获取cid,其他情况应该不会出错
|
||||
ipfsPath = dir.GetPath()
|
||||
switch d.Mode {
|
||||
case "ipfs":
|
||||
ipfsPath = path.Join("/ipfs", ipfsPath)
|
||||
case "ipns":
|
||||
ipfsPath = path.Join("/ipns", ipfsPath)
|
||||
case "mfs":
|
||||
fileStat, err := d.sh.FilesStat(ctx, ipfsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipfsPath = path.Join("/ipfs", fileStat.Hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("mode error")
|
||||
}
|
||||
path, _ = url.JoinPath("/ipfs", fileStat.Hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("mode error")
|
||||
}
|
||||
|
||||
dirs, err := d.sh.List(path)
|
||||
dirs, err := d.sh.List(ipfsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objlist := []model.Obj{}
|
||||
for _, file := range dirs {
|
||||
gateurl := *d.gateURL.JoinPath("/ipfs/" + file.Hash)
|
||||
gateurl.RawQuery = "filename=" + url.PathEscape(file.Name)
|
||||
objlist = append(objlist, &model.ObjectURL{
|
||||
Object: model.Object{ID: "/ipfs/" + file.Hash, Name: file.Name, Size: int64(file.Size), IsFolder: file.Type == 1},
|
||||
Url: model.Url{Url: gateurl.String()},
|
||||
})
|
||||
objlist = append(objlist, &model.Object{ID: file.Hash, Name: file.Name, Size: int64(file.Size), IsFolder: file.Type == 1})
|
||||
}
|
||||
|
||||
return objlist, nil
|
||||
}
|
||||
|
||||
func (d *IPFS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
gateurl := d.gateURL.JoinPath(file.GetID())
|
||||
gateurl.RawQuery = "filename=" + url.PathEscape(file.GetName())
|
||||
gateurl := d.gateURL.JoinPath("/ipfs/", file.GetID())
|
||||
gateurl.RawQuery = "filename=" + url.QueryEscape(file.GetName())
|
||||
return &model.Link{URL: gateurl.String()}, nil
|
||||
}
|
||||
|
||||
func (d *IPFS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
if d.Mode != "mfs" {
|
||||
return fmt.Errorf("only write in mfs mode")
|
||||
func (d *IPFS) Get(ctx context.Context, rawPath string) (model.Obj, error) {
|
||||
rawPath = path.Join(d.GetRootPath(), rawPath)
|
||||
var ipfsPath string
|
||||
switch d.Mode {
|
||||
case "ipfs":
|
||||
ipfsPath = path.Join("/ipfs", rawPath)
|
||||
case "ipns":
|
||||
ipfsPath = path.Join("/ipns", rawPath)
|
||||
case "mfs":
|
||||
fileStat, err := d.sh.FilesStat(ctx, rawPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipfsPath = path.Join("/ipfs", fileStat.Hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("mode error")
|
||||
}
|
||||
path := parentDir.GetPath()
|
||||
if path[len(path):] != "/" {
|
||||
path += "/"
|
||||
file, err := d.sh.FilesStat(ctx, ipfsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.sh.FilesMkdir(ctx, path+dirName)
|
||||
return &model.Object{ID: file.Hash, Name: path.Base(rawPath), Path: rawPath, Size: int64(file.Size), IsFolder: file.Type == "directory"}, nil
|
||||
}
|
||||
|
||||
func (d *IPFS) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
func (d *IPFS) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
|
||||
if d.Mode != "mfs" {
|
||||
return fmt.Errorf("only write in mfs mode")
|
||||
return nil, fmt.Errorf("only write in mfs mode")
|
||||
}
|
||||
return d.sh.FilesMv(ctx, srcObj.GetPath(), dstDir.GetPath())
|
||||
dirPath := parentDir.GetPath()
|
||||
err := d.sh.FilesMkdir(ctx, path.Join(dirPath, dirName), shell.FilesMkdir.Parents(true))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, err := d.sh.FilesStat(ctx, path.Join(dirPath, dirName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &model.Object{ID: file.Hash, Name: dirName, Path: path.Join(dirPath, dirName), Size: int64(file.Size), IsFolder: true}, nil
|
||||
}
|
||||
|
||||
func (d *IPFS) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
func (d *IPFS) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
||||
if d.Mode != "mfs" {
|
||||
return fmt.Errorf("only write in mfs mode")
|
||||
return nil, fmt.Errorf("only write in mfs mode")
|
||||
}
|
||||
newFileName := filepath.Dir(srcObj.GetPath()) + "/" + newName
|
||||
return d.sh.FilesMv(ctx, srcObj.GetPath(), strings.ReplaceAll(newFileName, "\\", "/"))
|
||||
dstPath := path.Join(dstDir.GetPath(), path.Base(srcObj.GetPath()))
|
||||
d.sh.FilesRm(ctx, dstPath, true)
|
||||
return &model.Object{ID: srcObj.GetID(), Name: srcObj.GetName(), Path: dstPath, Size: int64(srcObj.GetSize()), IsFolder: srcObj.IsDir()},
|
||||
d.sh.FilesMv(ctx, srcObj.GetPath(), dstDir.GetPath())
|
||||
}
|
||||
|
||||
func (d *IPFS) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
func (d *IPFS) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
|
||||
if d.Mode != "mfs" {
|
||||
return fmt.Errorf("only write in mfs mode")
|
||||
return nil, fmt.Errorf("only write in mfs mode")
|
||||
}
|
||||
newFileName := dstDir.GetPath() + "/" + filepath.Base(srcObj.GetPath())
|
||||
return d.sh.FilesCp(ctx, srcObj.GetPath(), strings.ReplaceAll(newFileName, "\\", "/"))
|
||||
dstPath := path.Join(path.Dir(srcObj.GetPath()), newName)
|
||||
d.sh.FilesRm(ctx, dstPath, true)
|
||||
return &model.Object{ID: srcObj.GetID(), Name: newName, Path: dstPath, Size: int64(srcObj.GetSize()),
|
||||
IsFolder: srcObj.IsDir()}, d.sh.FilesMv(ctx, srcObj.GetPath(), dstPath)
|
||||
}
|
||||
|
||||
func (d *IPFS) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
||||
if d.Mode != "mfs" {
|
||||
return nil, fmt.Errorf("only write in mfs mode")
|
||||
}
|
||||
dstPath := path.Join(dstDir.GetPath(), path.Base(srcObj.GetPath()))
|
||||
d.sh.FilesRm(ctx, dstPath, true)
|
||||
return &model.Object{ID: srcObj.GetID(), Name: srcObj.GetName(), Path: dstPath, Size: int64(srcObj.GetSize()), IsFolder: srcObj.IsDir()},
|
||||
d.sh.FilesCp(ctx, path.Join("/ipfs/", srcObj.GetID()), dstPath, shell.FilesCp.Parents(true))
|
||||
}
|
||||
|
||||
func (d *IPFS) Remove(ctx context.Context, obj model.Obj) error {
|
||||
|
@ -124,19 +160,25 @@ func (d *IPFS) Remove(ctx context.Context, obj model.Obj) error {
|
|||
return d.sh.FilesRm(ctx, obj.GetPath(), true)
|
||||
}
|
||||
|
||||
func (d *IPFS) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {
|
||||
func (d *IPFS) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
|
||||
if d.Mode != "mfs" {
|
||||
return fmt.Errorf("only write in mfs mode")
|
||||
return nil, fmt.Errorf("only write in mfs mode")
|
||||
}
|
||||
outHash, err := d.sh.Add(driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
|
||||
Reader: s,
|
||||
UpdateProgress: up,
|
||||
}))
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
err = d.sh.FilesCp(ctx, "/ipfs/"+outHash, dstDir.GetPath()+"/"+strings.ReplaceAll(s.GetName(), "\\", "/"))
|
||||
return err
|
||||
dstPath := path.Join(dstDir.GetPath(), s.GetName())
|
||||
if s.GetExist() != nil {
|
||||
d.sh.FilesRm(ctx, dstPath, true)
|
||||
}
|
||||
err = d.sh.FilesCp(ctx, path.Join("/ipfs/", outHash), dstPath, shell.FilesCp.Parents(true))
|
||||
gateurl := d.gateURL.JoinPath("/ipfs/", outHash)
|
||||
gateurl.RawQuery = "filename=" + url.QueryEscape(s.GetName())
|
||||
return &model.Object{ID: outHash, Name: s.GetName(), Path: dstPath, Size: int64(s.GetSize()), IsFolder: s.IsDir()}, err
|
||||
}
|
||||
|
||||
//func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
||||
|
|
|
@ -9,8 +9,8 @@ type Addition struct {
|
|||
// Usually one of two
|
||||
driver.RootPath
|
||||
Mode string `json:"mode" options:"ipfs,ipns,mfs" type:"select" required:"true"`
|
||||
Endpoint string `json:"endpoint" default:"http://127.0.0.1:5001"`
|
||||
Gateway string `json:"gateway" default:"http://127.0.0.1:8080"`
|
||||
Endpoint string `json:"endpoint" default:"http://127.0.0.1:5001" required:"true"`
|
||||
Gateway string `json:"gateway" default:"http://127.0.0.1:8080" required:"true"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
|
|
Loading…
Reference in New Issue