feat: local storage image thumbnail

pull/1604/head
Noah Hsu 2022-08-11 20:32:17 +08:00
parent fda4db71bf
commit af884010d1
19 changed files with 178 additions and 61 deletions

View File

@ -1,17 +1,25 @@
package local package local
import ( import (
"bytes"
"context" "context"
"io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
stdpath "path"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/operations" "github.com/alist-org/alist/v3/internal/operations"
"github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server/common"
"github.com/disintegration/imaging"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -54,7 +62,7 @@ func (d *Local) GetAddition() driver.Additional {
return d.Addition return d.Addition
} }
func (d *Local) List(ctx context.Context, dir model.Obj) ([]model.Obj, error) { func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
fullPath := dir.GetID() fullPath := dir.GetID()
rawFiles, err := ioutil.ReadDir(fullPath) rawFiles, err := ioutil.ReadDir(fullPath)
if err != nil { if err != nil {
@ -65,11 +73,22 @@ func (d *Local) List(ctx context.Context, dir model.Obj) ([]model.Obj, error) {
if strings.HasPrefix(f.Name(), ".") { if strings.HasPrefix(f.Name(), ".") {
continue continue
} }
file := model.Object{ thumb := ""
Name: f.Name(), if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
Modified: f.ModTime(), thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
Size: f.Size(), thumb = utils.EncodePath(thumb, true)
IsFolder: f.IsDir(), thumb += "?type=thumb"
}
file := model.ObjectThumbnail{
Object: model.Object{
Name: f.Name(),
Modified: f.ModTime(),
Size: f.Size(),
IsFolder: f.IsDir(),
},
Thumbnail: model.Thumbnail{
Thumbnail: thumb,
},
} }
files = append(files, &file) files = append(files, &file)
} }
@ -93,8 +112,30 @@ func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
fullPath := file.GetID() fullPath := file.GetID()
link := model.Link{ var link model.Link
FilePath: &fullPath, if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
imgData, err := ioutil.ReadFile(fullPath)
if err != nil {
return nil, err
}
srcBuf := bytes.NewBuffer(imgData)
image, err := imaging.Decode(srcBuf)
if err != nil {
return nil, err
}
thumbImg := imaging.Resize(image, 144, 0, imaging.Lanczos)
var buf bytes.Buffer
err = imaging.Encode(&buf, thumbImg, imaging.PNG)
if err != nil {
return nil, err
}
size := buf.Len()
link.Data = io.NopCloser(&buf)
link.Header = http.Header{
"Content-Length": []string{strconv.Itoa(size)},
}
} else {
link.FilePath = &fullPath
} }
return &link, nil return &link, nil
} }

View File

@ -7,6 +7,7 @@ import (
type Addition struct { type Addition struct {
driver.RootFolderPath driver.RootFolderPath
Thumbnail bool `json:"thumbnail" required:"true" help:"enable thumbnail"`
} }
var config = driver.Config{ var config = driver.Config{

View File

@ -43,7 +43,7 @@ func (d *Virtual) GetAddition() driver.Additional {
return d.Addition return d.Addition
} }
func (d *Virtual) List(ctx context.Context, dir model.Obj) ([]model.Obj, error) { func (d *Virtual) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
var res []model.Obj var res []model.Obj
for i := 0; i < d.NumFile; i++ { for i := 0; i < d.NumFile; i++ {
res = append(res, model.Object{ res = append(res, model.Object{

2
go.mod
View File

@ -25,6 +25,7 @@ require (
require ( require (
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect
@ -53,6 +54,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect

5
go.sum
View File

@ -17,6 +17,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA= github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk= github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@ -230,6 +232,9 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu251/+/jpBpZqir2mPdnU=
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=

View File

@ -32,7 +32,7 @@ type Reader interface {
// List files in the path // List files in the path
// if identify files by path, need to set ID with path,like path.Join(dir.GetID(), obj.GetName()) // if identify files by path, need to set ID with path,like path.Join(dir.GetID(), obj.GetName())
// if identify files by id, need to set ID with corresponding id // if identify files by id, need to set ID with corresponding id
List(ctx context.Context, dir model.Obj) ([]model.Obj, error) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error)
// Link get url/filepath/reader of file // Link get url/filepath/reader of file
Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error)
} }

View File

@ -51,7 +51,7 @@ func copyBetween2Storages(t *task.Task[uint64], srcStorage, dstStorage driver.Dr
} }
if srcObj.IsDir() { if srcObj.IsDir() {
t.SetStatus("src object is dir, listing objs") t.SetStatus("src object is dir, listing objs")
objs, err := operations.List(t.Ctx, srcStorage, srcObjPath) objs, err := operations.List(t.Ctx, srcStorage, srcObjPath, model.ListArgs{})
if err != nil { if err != nil {
return errors.WithMessagef(err, "failed list src [%s] objs", srcObjPath) return errors.WithMessagef(err, "failed list src [%s] objs", srcObjPath)
} }

View File

@ -24,7 +24,9 @@ func list(ctx context.Context, path string) ([]model.Obj, error) {
} }
return nil, errors.WithMessage(err, "failed get storage") return nil, errors.WithMessage(err, "failed get storage")
} }
objs, err := operations.List(ctx, storage, actualPath) objs, err := operations.List(ctx, storage, actualPath, model.ListArgs{
ReqPath: path,
})
if err != nil { if err != nil {
log.Errorf("%+v", err) log.Errorf("%+v", err)
if len(virtualFiles) != 0 { if len(virtualFiles) != 0 {

View File

@ -6,9 +6,14 @@ import (
"time" "time"
) )
type ListArgs struct {
ReqPath string
}
type LinkArgs struct { type LinkArgs struct {
IP string IP string
Header http.Header Header http.Header
Type string
} }
type Link struct { type Link struct {

View File

@ -28,8 +28,8 @@ type URL interface {
URL() string URL() string
} }
type Thumbnail interface { type Thumb interface {
Thumbnail() string Thumb() string
} }
type SetID interface { type SetID interface {

View File

@ -10,26 +10,39 @@ type Object struct {
IsFolder bool IsFolder bool
} }
func (f Object) GetName() string { func (o Object) GetName() string {
return f.Name return o.Name
} }
func (f Object) GetSize() int64 { func (o Object) GetSize() int64 {
return f.Size return o.Size
} }
func (f Object) ModTime() time.Time { func (o Object) ModTime() time.Time {
return f.Modified return o.Modified
} }
func (f Object) IsDir() bool { func (o Object) IsDir() bool {
return f.IsFolder return o.IsFolder
} }
func (f Object) GetID() string { func (o Object) GetID() string {
return f.ID return o.ID
} }
func (f *Object) SetID(id string) { func (o *Object) SetID(id string) {
f.ID = id o.ID = id
}
type Thumbnail struct {
Thumbnail string
}
func (t Thumbnail) Thumb() string {
return t.Thumbnail
}
type ObjectThumbnail struct {
Object
Thumbnail
} }

View File

@ -28,7 +28,7 @@ func ClearCache(storage driver.Driver, path string) {
} }
// List files in storage, not contains virtual file // List files in storage, not contains virtual file
func List(ctx context.Context, storage driver.Driver, path string, refresh ...bool) ([]model.Obj, error) { func List(ctx context.Context, storage driver.Driver, path string, args model.ListArgs, refresh ...bool) ([]model.Obj, error) {
path = utils.StandardizePath(path) path = utils.StandardizePath(path)
log.Debugf("operations.List %s", path) log.Debugf("operations.List %s", path)
dir, err := Get(ctx, storage, path) dir, err := Get(ctx, storage, path)
@ -39,7 +39,7 @@ func List(ctx context.Context, storage driver.Driver, path string, refresh ...bo
return nil, errors.WithStack(errs.NotFolder) return nil, errors.WithStack(errs.NotFolder)
} }
if storage.Config().NoCache { if storage.Config().NoCache {
return storage.List(ctx, dir) return storage.List(ctx, dir, args)
} }
key := stdpath.Join(storage.GetStorage().MountPath, path) key := stdpath.Join(storage.GetStorage().MountPath, path)
if len(refresh) == 0 || !refresh[0] { if len(refresh) == 0 || !refresh[0] {
@ -48,7 +48,7 @@ func List(ctx context.Context, storage driver.Driver, path string, refresh ...bo
} }
} }
files, err, _ := filesG.Do(key, func() ([]model.Obj, error) { files, err, _ := filesG.Do(key, func() ([]model.Obj, error) {
files, err := storage.List(ctx, dir) files, err := storage.List(ctx, dir, args)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "failed to list files") return nil, errors.WithMessage(err, "failed to list files")
} }
@ -99,7 +99,7 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er
} }
// not root folder // not root folder
dir, name := stdpath.Split(path) dir, name := stdpath.Split(path)
files, err := List(ctx, storage, dir) files, err := List(ctx, storage, dir, model.ListArgs{})
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "failed get parent list") return nil, errors.WithMessage(err, "failed get parent list")
} }
@ -148,7 +148,7 @@ func Link(ctx context.Context, storage driver.Driver, path string, args model.Li
return link, file, err return link, file, err
} }
// other api // Other api
func Other(ctx context.Context, storage driver.Driver, args model.FsOtherArgs) (interface{}, error) { func Other(ctx context.Context, storage driver.Driver, args model.FsOtherArgs) (interface{}, error) {
obj, err := Get(ctx, storage, args.Path) obj, err := Get(ctx, storage, args.Path)
if err != nil { if err != nil {

View File

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"net/url"
stdpath "path" stdpath "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -36,3 +37,26 @@ func Ext(path string) string {
} }
return ext return ext
} }
func EncodePath(path string, all ...bool) string {
seg := strings.Split(path, "/")
toReplace := []struct {
Src string
Dst string
}{
{Src: "%", Dst: "%25"},
{"%", "%25"},
{"?", "%3F"},
{"#", "%23"},
}
for i := range seg {
if len(all) > 0 && all[0] {
seg[i] = url.PathEscape(seg[i])
} else {
for j := range toReplace {
seg[i] = strings.ReplaceAll(seg[i], toReplace[j].Src, toReplace[j].Dst)
}
}
}
return strings.Join(seg, "/")
}

7
pkg/utils/path_test.go Normal file
View File

@ -0,0 +1,7 @@
package utils
import "testing"
func TestEncodePath(t *testing.T) {
t.Log(EncodePath("http://localhost:5244/d/123#.png"))
}

View File

@ -9,15 +9,17 @@ import (
"github.com/alist-org/alist/v3/internal/setting" "github.com/alist-org/alist/v3/internal/setting"
) )
func GetBaseUrl(r *http.Request) string { func GetApiUrl(r *http.Request) string {
baseUrl := setting.GetByKey(conf.ApiUrl) api := setting.GetByKey(conf.ApiUrl)
protocol := "http" protocol := "http"
if r.TLS != nil { if r != nil {
protocol = "https" if r.TLS != nil {
protocol = "https"
}
if api == "" {
api = fmt.Sprintf("%s://%s", protocol, r.Host)
}
} }
if baseUrl == "" { strings.TrimSuffix(api, "/")
baseUrl = fmt.Sprintf("%s://%s", protocol, r.Host) return api
}
strings.TrimSuffix(baseUrl, "/")
return baseUrl
} }

View File

@ -30,6 +30,7 @@ func Down(c *gin.Context) {
link, _, err := fs.Link(c, rawPath, model.LinkArgs{ link, _, err := fs.Link(c, rawPath, model.LinkArgs{
IP: c.ClientIP(), IP: c.ClientIP(),
Header: c.Request.Header, Header: c.Request.Header,
Type: c.Query("type"),
}) })
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
@ -52,13 +53,17 @@ func Proxy(c *gin.Context) {
if downProxyUrl != "" { if downProxyUrl != "" {
_, ok := c.GetQuery("d") _, ok := c.GetQuery("d")
if ok { if ok {
URL := fmt.Sprintf("%s%s?sign=%s", strings.Split(downProxyUrl, "\n")[0], rawPath, sign.Sign(filename)) URL := fmt.Sprintf("%s%s?sign=%s",
strings.Split(downProxyUrl, "\n")[0],
utils.EncodePath(rawPath),
sign.Sign(filename))
c.Redirect(302, URL) c.Redirect(302, URL)
return return
} }
} }
link, file, err := fs.Link(c, rawPath, model.LinkArgs{ link, file, err := fs.Link(c, rawPath, model.LinkArgs{
Header: c.Request.Header, Header: c.Request.Header,
Type: c.Query("type"),
}) })
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)

View File

@ -11,6 +11,7 @@ import (
"github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/internal/sign"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server/common" "github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -245,7 +246,10 @@ func Link(c *gin.Context) {
} }
if storage.Config().OnlyLocal { if storage.Config().OnlyLocal {
common.SuccessResp(c, model.Link{ common.SuccessResp(c, model.Link{
URL: fmt.Sprintf("%s/p%s?d&sign=%s", common.GetBaseUrl(c.Request), req.Path, sign.Sign(stdpath.Base(rawPath))), URL: fmt.Sprintf("%s/p%s?d&sign=%s",
common.GetApiUrl(c.Request),
utils.EncodePath(req.Path),
sign.Sign(stdpath.Base(rawPath))),
}) })
return return
} }

View File

@ -30,13 +30,13 @@ type DirReq struct {
} }
type ObjResp struct { type ObjResp struct {
Name string `json:"name"` Name string `json:"name"`
Size int64 `json:"size"` Size int64 `json:"size"`
IsDir bool `json:"is_dir"` IsDir bool `json:"is_dir"`
Modified time.Time `json:"modified"` Modified time.Time `json:"modified"`
Sign string `json:"sign"` Sign string `json:"sign"`
Thumbnail string `json:"thumbnail"` Thumb string `json:"thumb"`
Type int `json:"type"` Type int `json:"type"`
} }
type FsListResp struct { type FsListResp struct {
@ -169,22 +169,22 @@ func pagination(objs []model.Obj, req *common.PageReq) (int, []model.Obj) {
func toObjResp(objs []model.Obj) []ObjResp { func toObjResp(objs []model.Obj) []ObjResp {
var resp []ObjResp var resp []ObjResp
for _, obj := range objs { for _, obj := range objs {
thumbnail := "" thumb := ""
if t, ok := obj.(model.Thumbnail); ok { if t, ok := obj.(model.Thumb); ok {
thumbnail = t.Thumbnail() thumb = t.Thumb()
} }
tp := conf.FOLDER tp := conf.FOLDER
if !obj.IsDir() { if !obj.IsDir() {
tp = utils.GetFileType(obj.GetName()) tp = utils.GetFileType(obj.GetName())
} }
resp = append(resp, ObjResp{ resp = append(resp, ObjResp{
Name: obj.GetName(), Name: obj.GetName(),
Size: obj.GetSize(), Size: obj.GetSize(),
IsDir: obj.IsDir(), IsDir: obj.IsDir(),
Modified: obj.ModTime(), Modified: obj.ModTime(),
Sign: common.Sign(obj), Sign: common.Sign(obj),
Thumbnail: thumbnail, Thumb: thumb,
Type: tp, Type: tp,
}) })
} }
return resp return resp
@ -248,7 +248,10 @@ func FsGet(c *gin.Context) {
if storage.GetStorage().DownProxyUrl != "" { if storage.GetStorage().DownProxyUrl != "" {
rawURL = fmt.Sprintf("%s%s?sign=%s", strings.Split(storage.GetStorage().DownProxyUrl, "\n")[0], req.Path, sign.Sign(obj.GetName())) rawURL = fmt.Sprintf("%s%s?sign=%s", strings.Split(storage.GetStorage().DownProxyUrl, "\n")[0], req.Path, sign.Sign(obj.GetName()))
} else { } else {
rawURL = fmt.Sprintf("%s/p%s?sign=%s", common.GetBaseUrl(c.Request), req.Path, sign.Sign(obj.GetName())) rawURL = fmt.Sprintf("%s/p%s?sign=%s",
common.GetApiUrl(c.Request),
utils.EncodePath(req.Path),
sign.Sign(obj.GetName()))
} }
} else { } else {
// if storage is not proxy, use raw url by fs.Link // if storage is not proxy, use raw url by fs.Link

View File

@ -228,7 +228,10 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
} else if storage.Config().MustProxy() || storage.GetStorage().WebdavProxy() { } else if storage.Config().MustProxy() || storage.GetStorage().WebdavProxy() {
u := fmt.Sprintf("%s/p%s?sign=%s", common.GetBaseUrl(r), reqPath, sign.Sign(path.Base(reqPath))) u := fmt.Sprintf("%s/p%s?sign=%s",
common.GetApiUrl(r),
utils.EncodePath(reqPath),
sign.Sign(path.Base(reqPath)))
http.Redirect(w, r, u, 302) http.Redirect(w, r, u, 302)
} else { } else {
link, _, err := fs.Link(ctx, reqPath, model.LinkArgs{IP: utils.ClientIP(r)}) link, _, err := fs.Link(ctx, reqPath, model.LinkArgs{IP: utils.ClientIP(r)})