diff --git a/pkg/filesystem/driver/cos/handler.go b/pkg/filesystem/driver/cos/handler.go index 50b500c56e..709acef5a2 100644 --- a/pkg/filesystem/driver/cos/handler.go +++ b/pkg/filesystem/driver/cos/handler.go @@ -148,9 +148,9 @@ func (handler Driver) CORS() error { } // Get 获取文件 -func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { +func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) { // 获取文件源地址 - downloadURL, err := handler.Source(ctx, path, int64(model.GetIntSetting("preview_timeout", 60)), false, 0) + downloadURL, err := handler.Source(ctx, objectPath, int64(model.GetIntSetting("preview_timeout", 60)), false, 0) if err != nil { return nil, err } @@ -263,7 +263,7 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co } // Source 获取外链URL -func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) { +func (handler Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) { // 尝试从上下文获取文件名 fileName := "" if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok { @@ -285,10 +285,10 @@ func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDown options.ContentDescription = "attachment; filename=\"" + url.PathEscape(fileName) + "\"" } - return handler.signSourceURL(ctx, path, ttl, &options) + return handler.signSourceURL(ctx, objectPath, ttl, &options) } -func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, options *urlOption) (string, error) { +func (handler Driver) signSourceURL(ctx context.Context, objectPath string, ttl int64, options *urlOption) (string, error) { cdnURL, err := url.Parse(handler.Policy.BaseURL) if err != nil { return "", err @@ -296,7 +296,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, // 公有空间不需要签名 if !handler.Policy.IsPrivate { - file, err := url.Parse(path) + file, err := url.Parse(objectPath) if err != nil { return "", err } @@ -314,7 +314,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, return sourceURL.String(), nil } - presignedURL, err := handler.Client.Object.GetPresignedURL(ctx, http.MethodGet, path, + presignedURL, err := handler.Client.Object.GetPresignedURL(ctx, http.MethodGet, objectPath, handler.Policy.AccessKey, handler.Policy.SecretKey, time.Duration(ttl)*time.Second, options) if err != nil { return "", err @@ -324,6 +324,10 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, presignedURL.Host = cdnURL.Host presignedURL.Scheme = cdnURL.Scheme + // 支持代理域名使用子目录 + // Support sub-directories for proxy domain + presignedURL.Path = path.Join(cdnURL.Path, presignedURL.Path) + return presignedURL.String(), nil } @@ -374,8 +378,8 @@ func (handler Driver) CancelToken(ctx context.Context, uploadSession *serializer } // Meta 获取文件信息 -func (handler Driver) Meta(ctx context.Context, path string) (*MetaData, error) { - res, err := handler.Client.Object.Head(ctx, path, &cossdk.ObjectHeadOptions{}) +func (handler Driver) Meta(ctx context.Context, objectPath string) (*MetaData, error) { + res, err := handler.Client.Object.Head(ctx, objectPath, &cossdk.ObjectHeadOptions{}) if err != nil { return nil, err } diff --git a/pkg/filesystem/driver/local/handler.go b/pkg/filesystem/driver/local/handler.go index 85ba1af588..ef8eab8994 100644 --- a/pkg/filesystem/driver/local/handler.go +++ b/pkg/filesystem/driver/local/handler.go @@ -7,6 +7,7 @@ import ( "io" "net/url" "os" + "path" "path/filepath" model "github.com/cloudreve/Cloudreve/v3/models" @@ -76,9 +77,9 @@ func (handler Driver) List(ctx context.Context, path string, recursive bool) ([] } // Get 获取文件内容 -func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { +func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) { // 打开文件 - file, err := os.Open(util.RelativePath(path)) + file, err := os.Open(util.RelativePath(objectPath)) if err != nil { util.Log().Debug("Failed to open file: %s", err) return nil, err @@ -219,7 +220,7 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co } // Source 获取外链URL -func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) { +func (handler Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) { file, ok := ctx.Value(fsctx.FileModelCtx).(model.File) if !ok { return "", errors.New("failed to read file model context") @@ -268,7 +269,11 @@ func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDown finalURL := signedURI.String() if baseURL != nil { - finalURL = baseURL.ResolveReference(signedURI).String() + // 支持代理域名使用子目录 + // Support sub-directories for proxy domain + baseURL.Path = path.Join(baseURL.Path, signedURI.Path) + baseURL.RawQuery = signedURI.RawQuery + finalURL = baseURL.String() } return finalURL, nil diff --git a/pkg/filesystem/driver/onedrive/handler.go b/pkg/filesystem/driver/onedrive/handler.go index 149fdba8cc..df613dd3ca 100644 --- a/pkg/filesystem/driver/onedrive/handler.go +++ b/pkg/filesystem/driver/onedrive/handler.go @@ -86,11 +86,11 @@ func (handler Driver) List(ctx context.Context, base string, recursive bool) ([] } // Get 获取文件 -func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { +func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) { // 获取文件源地址 downloadURL, err := handler.Source( ctx, - path, + objectPath, 60, false, 0, @@ -162,12 +162,12 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co // Source 获取外链URL func (handler Driver) Source( ctx context.Context, - path string, + objectPath string, ttl int64, isDownload bool, speed int, ) (string, error) { - cacheKey := fmt.Sprintf("onedrive_source_%d_%s", handler.Policy.ID, path) + cacheKey := fmt.Sprintf("onedrive_source_%d_%s", handler.Policy.ID, objectPath) if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok { cacheKey = fmt.Sprintf("onedrive_source_file_%d_%d", file.UpdatedAt.Unix(), file.ID) } @@ -178,7 +178,7 @@ func (handler Driver) Source( } // 缓存不存在,重新获取 - res, err := handler.Client.Meta(ctx, "", path) + res, err := handler.Client.Meta(ctx, "", objectPath) if err == nil { // 写入新的缓存 cache.Set( @@ -206,6 +206,11 @@ func (handler Driver) replaceSourceHost(origin string) (string, error) { // 替换反代地址 source.Scheme = cdn.Scheme source.Host = cdn.Host + + // 支持代理域名使用子目录 + // Support sub-directories for proxy domain + source.Path = path.Join(cdn.Path, source.Path) + return source.String(), nil } diff --git a/pkg/filesystem/driver/oss/handler.go b/pkg/filesystem/driver/oss/handler.go index 2ae50a375e..5c602aca9d 100644 --- a/pkg/filesystem/driver/oss/handler.go +++ b/pkg/filesystem/driver/oss/handler.go @@ -186,7 +186,7 @@ func (handler *Driver) List(ctx context.Context, base string, recursive bool) ([ } // Get 获取文件 -func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { +func (handler *Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) { // 通过VersionID禁止缓存 ctx = context.WithValue(ctx, VersionID, time.Now().UnixNano()) @@ -194,7 +194,7 @@ func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, ctx = context.WithValue(ctx, fsctx.ForceUsePublicEndpointCtx, false) // 获取文件源地址 - downloadURL, err := handler.Source(ctx, path, int64(model.GetIntSetting("preview_timeout", 60)), false, 0) + downloadURL, err := handler.Source(ctx, objectPath, int64(model.GetIntSetting("preview_timeout", 60)), false, 0) if err != nil { return nil, err } @@ -334,7 +334,7 @@ func (handler *Driver) Thumb(ctx context.Context, file *model.File) (*response.C } // Source 获取外链URL -func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) { +func (handler *Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) { // 初始化客户端 usePublicEndpoint := true if forceUsePublicEndpoint, ok := ctx.Value(fsctx.ForceUsePublicEndpointCtx).(bool); ok { @@ -369,11 +369,11 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow signOptions = append(signOptions, oss.TrafficLimitParam(int64(speed))) } - return handler.signSourceURL(ctx, path, ttl, signOptions) + return handler.signSourceURL(ctx, objectPath, ttl, signOptions) } -func (handler *Driver) signSourceURL(ctx context.Context, path string, ttl int64, options []oss.Option) (string, error) { - signedURL, err := handler.bucket.SignURL(path, oss.HTTPGet, ttl, options...) +func (handler *Driver) signSourceURL(ctx context.Context, objectPath string, ttl int64, options []oss.Option) (string, error) { + signedURL, err := handler.bucket.SignURL(objectPath, oss.HTTPGet, ttl, options...) if err != nil { return "", err } @@ -401,6 +401,10 @@ func (handler *Driver) signSourceURL(ctx context.Context, path string, ttl int64 } finalURL.Host = cdnURL.Host finalURL.Scheme = cdnURL.Scheme + + // 支持代理域名使用子目录 + // Support sub-directories for proxy domain + finalURL.Path = path.Join(cdnURL.Path, finalURL.Path) } return finalURL.String(), nil diff --git a/pkg/filesystem/driver/remote/handler.go b/pkg/filesystem/driver/remote/handler.go index 5918f3b4e4..7e9373e680 100644 --- a/pkg/filesystem/driver/remote/handler.go +++ b/pkg/filesystem/driver/remote/handler.go @@ -116,7 +116,7 @@ func (handler *Driver) getAPIUrl(scope string, routes ...string) string { } // Get 获取文件内容 -func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { +func (handler *Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) { // 尝试获取速度限制 speedLimit := 0 if user, ok := ctx.Value(fsctx.UserCtx).(model.User); ok { @@ -124,7 +124,7 @@ func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, } // 获取文件源地址 - downloadURL, err := handler.Source(ctx, path, 0, true, speedLimit) + downloadURL, err := handler.Source(ctx, objectPath, 0, true, speedLimit) if err != nil { return nil, err } @@ -233,7 +233,7 @@ func (handler *Driver) Thumb(ctx context.Context, file *model.File) (*response.C } // Source 获取外链URL -func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) { +func (handler *Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) { // 尝试从上下文获取文件名 fileName := "file" if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok { @@ -263,7 +263,7 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow } // 签名下载地址 - sourcePath := base64.RawURLEncoding.EncodeToString([]byte(path)) + sourcePath := base64.RawURLEncoding.EncodeToString([]byte(objectPath)) signedURI, err = auth.SignURI( handler.AuthInstance, fmt.Sprintf("%s/%d/%s/%s", controller, speed, sourcePath, url.PathEscape(fileName)), @@ -274,9 +274,12 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow return "", serializer.NewError(serializer.CodeEncryptError, "Failed to sign URL", err) } - finalURL := serverURL.ResolveReference(signedURI).String() - return finalURL, nil + // 支持代理域名使用子目录 + // Support sub-directories for proxy domain + serverURL.Path = path.Join(serverURL.Path, signedURI.Path) + serverURL.RawQuery = signedURI.RawQuery + return serverURL.String(), nil } // Token 获取上传策略和认证Token