mirror of
https://github.com/halejohn/Cloudreve.git
synced 2026-01-26 09:34:57 +08:00
Refactor: use universal FileHeader when handling file upload, remove usage of global ctx with FileHeader, SavePath, DisableOverwrite
This commit is contained in:
@@ -183,9 +183,9 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
opt := &cossdk.ObjectPutOptions{}
|
||||
_, err := handler.Client.Object.Put(ctx, dst, file, opt)
|
||||
_, err := handler.Client.Object.Put(ctx, file.GetSavePath(), file, opt)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -324,13 +324,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64,
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
// 读取上下文中生成的存储路径
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 生成回调地址
|
||||
siteURL := model.GetSiteURL()
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/cos/" + uploadSession.Key)
|
||||
@@ -338,13 +332,13 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
|
||||
// 上传策略
|
||||
startTime := time.Now()
|
||||
endTime := startTime.Add(time.Duration(TTL) * time.Second)
|
||||
endTime := startTime.Add(time.Duration(ttl) * time.Second)
|
||||
keyTime := fmt.Sprintf("%d;%d", startTime.Unix(), endTime.Unix())
|
||||
postPolicy := UploadPolicy{
|
||||
Expiration: endTime.UTC().Format(time.RFC3339),
|
||||
Conditions: []interface{}{
|
||||
map[string]string{"bucket": handler.Policy.BucketName},
|
||||
map[string]string{"$key": savePath},
|
||||
map[string]string{"$key": file.GetSavePath()},
|
||||
map[string]string{"x-cos-meta-callback": apiURL},
|
||||
map[string]string{"x-cos-meta-key": uploadSession.Key},
|
||||
map[string]string{"q-sign-algorithm": "sha1"},
|
||||
|
||||
@@ -2,9 +2,9 @@ package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/response"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"io"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
type Handler interface {
|
||||
// 上传文件, dst为文件存储路径,size 为文件大小。上下文关闭
|
||||
// 时,应取消上传并清理临时文件
|
||||
Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error
|
||||
Put(ctx context.Context, file fsctx.FileHeader) error
|
||||
|
||||
// 删除一个或多个给定路径的文件,返回删除失败的文件路径列表及错误
|
||||
Delete(ctx context.Context, files []string) ([]string, error)
|
||||
@@ -30,7 +30,7 @@ type Handler interface {
|
||||
Source(ctx context.Context, path string, url url.URL, ttl int64, isDownload bool, speed int) (string, error)
|
||||
|
||||
// Token 获取有效期为ttl的上传凭证和签名
|
||||
Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error)
|
||||
Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error)
|
||||
|
||||
// List 递归列取远程端path路径下文件、目录,不包含path本身,
|
||||
// 返回的对象路径以path作为起始根目录.
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// FileStream 用户传来的文件
|
||||
type FileStream struct {
|
||||
File io.ReadCloser
|
||||
Size uint64
|
||||
VirtualPath string
|
||||
Name string
|
||||
MIMEType string
|
||||
}
|
||||
|
||||
func (file FileStream) Read(p []byte) (n int, err error) {
|
||||
return file.File.Read(p)
|
||||
}
|
||||
|
||||
func (file FileStream) GetMIMEType() string {
|
||||
return file.MIMEType
|
||||
}
|
||||
|
||||
func (file FileStream) GetSize() uint64 {
|
||||
return file.Size
|
||||
}
|
||||
|
||||
func (file FileStream) Close() error {
|
||||
return file.File.Close()
|
||||
}
|
||||
|
||||
func (file FileStream) GetFileName() string {
|
||||
return file.Name
|
||||
}
|
||||
|
||||
func (file FileStream) GetVirtualPath() string {
|
||||
return file.VirtualPath
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFileStream_GetFileName(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
file := FileStream{Name: "123"}
|
||||
asserts.Equal("123", file.GetFileName())
|
||||
}
|
||||
|
||||
func TestFileStream_GetMIMEType(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
file := FileStream{MIMEType: "123"}
|
||||
asserts.Equal("123", file.GetMIMEType())
|
||||
}
|
||||
|
||||
func TestFileStream_GetSize(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
file := FileStream{Size: 123}
|
||||
asserts.Equal(uint64(123), file.GetSize())
|
||||
}
|
||||
|
||||
func TestFileStream_Read(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
file := FileStream{
|
||||
File: ioutil.NopCloser(strings.NewReader("123")),
|
||||
}
|
||||
var p = make([]byte, 3)
|
||||
{
|
||||
n, err := file.Read(p)
|
||||
asserts.Equal(3, n)
|
||||
asserts.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileStream_Close(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
file := FileStream{
|
||||
File: ioutil.NopCloser(strings.NewReader("123")),
|
||||
}
|
||||
err := file.Close()
|
||||
asserts.NoError(err)
|
||||
}
|
||||
@@ -83,12 +83,12 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
dst = util.RelativePath(filepath.FromSlash(dst))
|
||||
dst := util.RelativePath(filepath.FromSlash(file.GetSavePath()))
|
||||
|
||||
// 如果禁止了 Overwrite,则检查是否有重名冲突
|
||||
if ctx.Value(fsctx.DisableOverwrite) != nil {
|
||||
// 如果非 Overwrite,则检查是否有重名冲突
|
||||
if file.GetMode() != fsctx.Overwrite {
|
||||
if util.Exists(dst) {
|
||||
util.Log().Warning("物理同名文件已存在或不可用: %s", dst)
|
||||
return errors.New("物理同名文件已存在或不可用")
|
||||
@@ -214,7 +214,7 @@ func (handler Driver) Source(
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token,本地策略直接返回空值
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
return serializer.UploadCredential{
|
||||
SessionID: uploadSession.Key,
|
||||
}, nil
|
||||
|
||||
@@ -257,13 +257,16 @@ func (client *Client) UploadChunk(ctx context.Context, uploadURL string, chunk *
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (client *Client) Upload(ctx context.Context, dst string, size int, file io.Reader) error {
|
||||
func (client *Client) Upload(ctx context.Context, file fsctx.FileHeader) error {
|
||||
// 决定是否覆盖文件
|
||||
overwrite := "replace"
|
||||
if ctx.Value(fsctx.DisableOverwrite) != nil {
|
||||
if file.GetMode() != fsctx.Overwrite {
|
||||
overwrite = "fail"
|
||||
}
|
||||
|
||||
size := int(file.GetSize())
|
||||
dst := file.GetSavePath()
|
||||
|
||||
// 小文件,使用简单上传接口上传
|
||||
if size <= int(SmallFileSize) {
|
||||
_, err := client.SimpleUpload(ctx, dst, file, int64(size), WithConflictBehavior(overwrite))
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -121,9 +120,9 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
return handler.Client.Upload(ctx, dst, int(size), file)
|
||||
return handler.Client.Upload(ctx, file)
|
||||
}
|
||||
|
||||
// Delete 删除一个或多个文件,
|
||||
@@ -223,20 +222,10 @@ func (handler Driver) replaceSourceHost(origin string) (string, error) {
|
||||
}
|
||||
|
||||
// Token 获取上传会话URL
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
|
||||
// 读取上下文中生成的存储路径和文件大小
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
fileSize, ok := ctx.Value(fsctx.FileSizeCtx).(uint64)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取文件大小")
|
||||
}
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
|
||||
// 如果小于4MB,则由服务端中转
|
||||
if fileSize <= SmallFileSize {
|
||||
if file.GetSize() <= SmallFileSize {
|
||||
return serializer.UploadCredential{}, nil
|
||||
}
|
||||
|
||||
@@ -245,13 +234,13 @@ func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *seria
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/onedrive/finish/" + uploadSession.Key)
|
||||
apiURL := siteURL.ResolveReference(apiBaseURI)
|
||||
|
||||
uploadURL, err := handler.Client.CreateUploadSession(ctx, savePath, WithConflictBehavior("fail"))
|
||||
uploadURL, err := handler.Client.CreateUploadSession(ctx, file.GetSavePath(), WithConflictBehavior("fail"))
|
||||
if err != nil {
|
||||
return serializer.UploadCredential{}, err
|
||||
}
|
||||
|
||||
// 监控回调及上传
|
||||
go handler.Client.MonitorUpload(uploadURL, uploadSession.Key, savePath, fileSize, ttl)
|
||||
go handler.Client.MonitorUpload(uploadURL, uploadSession.Key, file.GetSavePath(), file.GetSize(), ttl)
|
||||
|
||||
return serializer.UploadCredential{
|
||||
Policy: uploadURL,
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
// 无法获取文件路径
|
||||
{
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileSizeCtx, uint64(10))
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.Error(err)
|
||||
asserts.Equal(serializer.UploadCredential{}, res)
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
// 无法获取文件大小
|
||||
{
|
||||
ctx := context.WithValue(context.Background(), fsctx.SavePathCtx, "/123")
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.Error(err)
|
||||
asserts.Equal(serializer.UploadCredential{}, res)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
{
|
||||
ctx := context.WithValue(context.Background(), fsctx.SavePathCtx, "/123")
|
||||
ctx = context.WithValue(ctx, fsctx.FileSizeCtx, uint64(10))
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.NoError(err)
|
||||
asserts.Equal(serializer.UploadCredential{}, res)
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
handler.Client.Request = clientMock
|
||||
ctx := context.WithValue(context.Background(), fsctx.SavePathCtx, "/123")
|
||||
ctx = context.WithValue(ctx, fsctx.FileSizeCtx, uint64(20*1024*1024))
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.Error(err)
|
||||
asserts.Equal(serializer.UploadCredential{}, res)
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
FinishCallback("key")
|
||||
}()
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.NoError(err)
|
||||
asserts.Equal("123321", res.Policy)
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
|
||||
// 初始化客户端
|
||||
@@ -237,7 +237,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
|
||||
// 是否允许覆盖
|
||||
overwrite := true
|
||||
if ctx.Value(fsctx.DisableOverwrite) != nil {
|
||||
if file.GetMode() != fsctx.Overwrite {
|
||||
overwrite = false
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
err := handler.bucket.PutObject(dst, file, options...)
|
||||
err := handler.bucket.PutObject(file.GetSavePath(), file, options...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -397,13 +397,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64,
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
// 读取上下文中生成的存储路径
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 生成回调地址
|
||||
siteURL := model.GetSiteURL()
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/oss/" + uploadSession.Key)
|
||||
@@ -418,10 +412,10 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
|
||||
// 上传策略
|
||||
postPolicy := UploadPolicy{
|
||||
Expiration: time.Now().UTC().Add(time.Duration(TTL) * time.Second).Format(time.RFC3339),
|
||||
Expiration: time.Now().UTC().Add(time.Duration(ttl) * time.Second).Format(time.RFC3339),
|
||||
Conditions: []interface{}{
|
||||
map[string]string{"bucket": handler.Policy.BucketName},
|
||||
[]string{"starts-with", "$key", path.Dir(savePath)},
|
||||
[]string{"starts-with", "$key", path.Dir(file.GetSavePath())},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -430,7 +424,7 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
[]interface{}{"content-length-range", 0, handler.Policy.MaxSize})
|
||||
}
|
||||
|
||||
return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, TTL)
|
||||
return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, ttl)
|
||||
}
|
||||
|
||||
func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback CallbackPolicy, TTL int64) (serializer.UploadCredential, error) {
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
{
|
||||
ctx := context.WithValue(context.Background(), fsctx.SavePathCtx, "/123")
|
||||
cache.Set("setting_siteURL", "http://test.cloudreve.org", 0)
|
||||
res, err := handler.Token(ctx, 10, "key")
|
||||
res, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.NoError(err)
|
||||
asserts.NotEmpty(res.Policy)
|
||||
asserts.NotEmpty(res.Token)
|
||||
@@ -91,7 +91,7 @@ func TestDriver_Token(t *testing.T) {
|
||||
// 上下文错误
|
||||
{
|
||||
ctx := context.Background()
|
||||
_, err := handler.Token(ctx, 10, "key")
|
||||
_, err := handler.Token(ctx, 10, "key", nil)
|
||||
asserts.Error(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -144,7 +143,7 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
|
||||
// 凭证有效期
|
||||
@@ -153,10 +152,10 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
// 生成上传策略
|
||||
putPolicy := storage.PutPolicy{
|
||||
// 指定为覆盖策略
|
||||
Scope: fmt.Sprintf("%s:%s", handler.Policy.BucketName, dst),
|
||||
SaveKey: dst,
|
||||
Scope: fmt.Sprintf("%s:%s", handler.Policy.BucketName, file.GetSavePath()),
|
||||
SaveKey: file.GetSavePath(),
|
||||
ForceSaveKey: true,
|
||||
FsizeLimit: int64(size),
|
||||
FsizeLimit: int64(file.GetSize()),
|
||||
}
|
||||
// 是否开启了MIMEType限制
|
||||
if handler.Policy.OptionsSerialized.MimeType != "" {
|
||||
@@ -178,7 +177,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
}
|
||||
|
||||
// 开始上传
|
||||
err = formUploader.Put(ctx, &ret, token.Token, dst, file, int64(size), &putExtra)
|
||||
err = formUploader.Put(ctx, &ret, token.Token, file.GetSavePath(), file, int64(file.GetSize()), &putExtra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -274,25 +273,19 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64)
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 生成回调地址
|
||||
siteURL := model.GetSiteURL()
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/qiniu/" + uploadSession.Key)
|
||||
apiURL := siteURL.ResolveReference(apiBaseURI)
|
||||
|
||||
// 读取上下文中生成的存储路径
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
|
||||
// 创建上传策略
|
||||
putPolicy := storage.PutPolicy{
|
||||
Scope: handler.Policy.BucketName,
|
||||
CallbackURL: apiURL.String(),
|
||||
CallbackBody: `{"name":"$(fname)","source_name":"$(key)","size":$(fsize),"pic_info":"$(imageInfo.width),$(imageInfo.height)"}`,
|
||||
CallbackBodyType: "application/json",
|
||||
SaveKey: savePath,
|
||||
SaveKey: file.GetSavePath(),
|
||||
ForceSaveKey: true,
|
||||
FsizeLimit: int64(handler.Policy.MaxSize),
|
||||
}
|
||||
@@ -301,7 +294,7 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
putPolicy.MimeLimit = handler.Policy.OptionsSerialized.MimeType
|
||||
}
|
||||
|
||||
return handler.getUploadCredential(ctx, putPolicy, TTL)
|
||||
return handler.getUploadCredential(ctx, putPolicy, ttl)
|
||||
}
|
||||
|
||||
// getUploadCredential 签名上传策略
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -134,7 +133,7 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
|
||||
// 凭证有效期
|
||||
@@ -142,10 +141,10 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
|
||||
// 生成上传策略
|
||||
policy := serializer.UploadPolicy{
|
||||
SavePath: path.Dir(dst),
|
||||
FileName: path.Base(dst),
|
||||
SavePath: path.Dir(file.GetSavePath()),
|
||||
FileName: path.Base(file.GetSavePath()),
|
||||
AutoRename: false,
|
||||
MaxSize: size,
|
||||
MaxSize: file.GetSize(),
|
||||
}
|
||||
credential, err := handler.getUploadCredential(ctx, policy, int64(credentialTTL))
|
||||
if err != nil {
|
||||
@@ -153,11 +152,11 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
}
|
||||
|
||||
// 对文件名进行URLEncode
|
||||
fileName := url.QueryEscape(path.Base(dst))
|
||||
fileName := url.QueryEscape(path.Base(file.GetSavePath()))
|
||||
|
||||
// 决定是否要禁用文件覆盖
|
||||
overwrite := "true"
|
||||
if ctx.Value(fsctx.DisableOverwrite) != nil {
|
||||
if file.GetMode() != fsctx.Overwrite {
|
||||
overwrite = "false"
|
||||
}
|
||||
|
||||
@@ -171,7 +170,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
"X-Cr-FileName": {fileName},
|
||||
"X-Cr-Overwrite": {overwrite},
|
||||
}),
|
||||
request.WithContentLength(int64(size)),
|
||||
request.WithContentLength(int64(file.GetSize())),
|
||||
request.WithTimeout(time.Duration(0)),
|
||||
request.WithMasterMeta(),
|
||||
request.WithSlaveMeta(handler.Policy.AccessKey),
|
||||
@@ -305,7 +304,7 @@ func (handler Driver) Source(
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 生成回调地址
|
||||
siteURL := model.GetSiteURL()
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/remote/" + uploadSession.Key)
|
||||
@@ -320,7 +319,7 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
AllowedExtension: handler.Policy.OptionsSerialized.FileType,
|
||||
CallbackURL: apiURL.String(),
|
||||
}
|
||||
return handler.getUploadCredential(ctx, policy, TTL)
|
||||
return handler.getUploadCredential(ctx, policy, ttl)
|
||||
}
|
||||
|
||||
func (handler Driver) getUploadCredential(ctx context.Context, policy serializer.UploadPolicy, TTL int64) (serializer.UploadCredential, error) {
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestHandler_Token(t *testing.T) {
|
||||
// 成功
|
||||
{
|
||||
cache.Set("setting_siteURL", "http://test.cloudreve.org", 0)
|
||||
credential, err := handler.Token(ctx, 10, "123")
|
||||
credential, err := handler.Token(ctx, 10, "123", nil)
|
||||
asserts.NoError(err)
|
||||
policy, err := serializer.DecodeUploadPolicy(credential.Policy)
|
||||
asserts.NoError(err)
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -198,7 +197,7 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
|
||||
// 初始化客户端
|
||||
if err := handler.InitS3Client(); err != nil {
|
||||
@@ -207,6 +206,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
|
||||
uploader := s3manager.NewUploader(handler.sess)
|
||||
|
||||
dst := file.GetSavePath()
|
||||
_, err := uploader.Upload(&s3manager.UploadInput{
|
||||
Bucket: &handler.Policy.BucketName,
|
||||
Key: &dst,
|
||||
@@ -324,14 +324,7 @@ func (handler Driver) Source(
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
|
||||
// 读取上下文中生成的存储路径和文件大小
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 生成回调地址
|
||||
siteURL := model.GetSiteURL()
|
||||
apiBaseURI, _ := url.Parse("/api/v3/callback/s3/" + uploadSession.Key)
|
||||
@@ -339,10 +332,10 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
|
||||
// 上传策略
|
||||
putPolicy := UploadPolicy{
|
||||
Expiration: time.Now().UTC().Add(time.Duration(TTL) * time.Second).Format(time.RFC3339),
|
||||
Expiration: time.Now().UTC().Add(time.Duration(ttl) * time.Second).Format(time.RFC3339),
|
||||
Conditions: []interface{}{
|
||||
map[string]string{"bucket": handler.Policy.BucketName},
|
||||
[]string{"starts-with", "$key", savePath},
|
||||
[]string{"starts-with", "$key", file.GetSavePath()},
|
||||
[]string{"starts-with", "$success_action_redirect", apiURL.String()},
|
||||
[]string{"starts-with", "$name", ""},
|
||||
[]string{"starts-with", "$Content-Type", ""},
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/cluster"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/driver"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/response"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"io"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
@@ -27,8 +27,8 @@ func NewDriver(master cluster.Node, handler driver.Handler, policy *model.Policy
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
return d.handler.Put(ctx, file, dst, size)
|
||||
func (d *Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
return d.handler.Put(ctx, file)
|
||||
}
|
||||
|
||||
func (d *Driver) Delete(ctx context.Context, files []string) ([]string, error) {
|
||||
@@ -47,7 +47,7 @@ func (d *Driver) Source(ctx context.Context, path string, url url.URL, ttl int64
|
||||
return "", ErrNotImplemented
|
||||
}
|
||||
|
||||
func (d *Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
func (d *Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
return serializer.UploadCredential{}, ErrNotImplemented
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/mq"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/request"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"io"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
@@ -50,7 +49,7 @@ func NewDriver(node cluster.Node, handler driver.Handler, policy *model.Policy)
|
||||
}
|
||||
|
||||
// Put 将ctx中指定的从机物理文件由从机上传到目标存储策略
|
||||
func (d *Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (d *Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
src, ok := ctx.Value(fsctx.SlaveSrcPath).(string)
|
||||
if !ok {
|
||||
return ErrSlaveSrcPathNotExist
|
||||
@@ -58,7 +57,7 @@ func (d *Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size u
|
||||
|
||||
req := serializer.SlaveTransferReq{
|
||||
Src: src,
|
||||
Dst: dst,
|
||||
Dst: file.GetSavePath(),
|
||||
Policy: d.policy,
|
||||
}
|
||||
|
||||
@@ -112,7 +111,7 @@ func (d *Driver) Source(ctx context.Context, path string, url url.URL, ttl int64
|
||||
return "", ErrNotImplemented
|
||||
}
|
||||
|
||||
func (d *Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
func (d *Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
return serializer.UploadCredential{}, ErrNotImplemented
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -146,7 +145,7 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
||||
}
|
||||
|
||||
// Put 将文件流保存到指定目录
|
||||
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
|
||||
func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
|
||||
defer file.Close()
|
||||
|
||||
up := upyun.NewUpYun(&upyun.UpYunConfig{
|
||||
@@ -155,7 +154,7 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||
Password: handler.Policy.SecretKey,
|
||||
})
|
||||
err := up.Put(&upyun.PutObjectConfig{
|
||||
Path: dst,
|
||||
Path: file.GetSavePath(),
|
||||
Reader: file,
|
||||
})
|
||||
|
||||
@@ -311,17 +310,7 @@ func (handler Driver) signURL(ctx context.Context, path *url.URL, TTL int64) (st
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *serializer.UploadSession) (serializer.UploadCredential, error) {
|
||||
// 读取上下文中生成的存储路径和文件大小
|
||||
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
|
||||
}
|
||||
fileSize, ok := ctx.Value(fsctx.FileSizeCtx).(uint64)
|
||||
if !ok {
|
||||
return serializer.UploadCredential{}, errors.New("无法获取文件大小")
|
||||
}
|
||||
|
||||
func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *serializer.UploadSession, file fsctx.FileHeader) (serializer.UploadCredential, error) {
|
||||
// 检查文件大小
|
||||
|
||||
// 生成回调地址
|
||||
@@ -333,11 +322,11 @@ func (handler Driver) Token(ctx context.Context, TTL int64, uploadSession *seria
|
||||
putPolicy := UploadPolicy{
|
||||
Bucket: handler.Policy.BucketName,
|
||||
// TODO escape
|
||||
SaveKey: savePath,
|
||||
Expiration: time.Now().Add(time.Duration(TTL) * time.Second).Unix(),
|
||||
SaveKey: file.GetSavePath(),
|
||||
Expiration: time.Now().Add(time.Duration(ttl) * time.Second).Unix(),
|
||||
CallbackURL: apiURL.String(),
|
||||
ContentLength: fileSize,
|
||||
ContentLengthRange: fmt.Sprintf("0,%d", fileSize),
|
||||
ContentLength: file.GetSize(),
|
||||
ContentLengthRange: fmt.Sprintf("0,%d", file.GetSize()),
|
||||
AllowFileType: strings.Join(handler.Policy.OptionsSerialized.FileType, ","),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user