mirror of https://github.com/cloudreve/Cloudreve
Feat: support setting "last modified" props when creating upload session
parent
e37e93a7b6
commit
6fdf77e00e
|
@ -19,7 +19,7 @@ const (
|
||||||
type FileStream struct {
|
type FileStream struct {
|
||||||
Mode WriteMode
|
Mode WriteMode
|
||||||
Hidden bool
|
Hidden bool
|
||||||
LastModified time.Time
|
LastModified *time.Time
|
||||||
Metadata map[string]string
|
Metadata map[string]string
|
||||||
File io.ReadCloser
|
File io.ReadCloser
|
||||||
Size uint64
|
Size uint64
|
||||||
|
@ -61,7 +61,7 @@ func (file *FileStream) GetMetadata() map[string]string {
|
||||||
return file.Metadata
|
return file.Metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *FileStream) GetLastModified() time.Time {
|
func (file *FileStream) GetLastModified() *time.Time {
|
||||||
return file.LastModified
|
return file.LastModified
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ type FileHeader interface {
|
||||||
GetVirtualPath() string
|
GetVirtualPath() string
|
||||||
GetMode() WriteMode
|
GetMode() WriteMode
|
||||||
GetMetadata() map[string]string
|
GetMetadata() map[string]string
|
||||||
GetLastModified() time.Time
|
GetLastModified() *time.Time
|
||||||
IsHidden() bool
|
IsHidden() bool
|
||||||
GetSavePath() string
|
GetSavePath() string
|
||||||
SetSize(uint64)
|
SetSize(uint64)
|
||||||
|
|
|
@ -149,7 +149,7 @@ func (fs *FileSystem) CancelUpload(ctx context.Context, path string, file fsctx.
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUploadSession 创建上传会话
|
// CreateUploadSession 创建上传会话
|
||||||
func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size uint64, name string) (*serializer.UploadCredential, error) {
|
func (fs *FileSystem) CreateUploadSession(ctx context.Context, file *fsctx.FileStream) (*serializer.UploadCredential, error) {
|
||||||
// 获取相关有效期设置
|
// 获取相关有效期设置
|
||||||
credentialTTL := model.GetIntSetting("upload_credential_timeout", 3600)
|
credentialTTL := model.GetIntSetting("upload_credential_timeout", 3600)
|
||||||
callBackSessionTTL := model.GetIntSetting("upload_session_timeout", 86400)
|
callBackSessionTTL := model.GetIntSetting("upload_session_timeout", 86400)
|
||||||
|
@ -157,16 +157,12 @@ func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size
|
||||||
callbackKey := uuid.Must(uuid.NewV4()).String()
|
callbackKey := uuid.Must(uuid.NewV4()).String()
|
||||||
|
|
||||||
// 创建隐藏的文件,同时校验文件信息
|
// 创建隐藏的文件,同时校验文件信息
|
||||||
file := &fsctx.FileStream{
|
file.Mode = fsctx.Nop
|
||||||
Size: size,
|
file.Hidden = true
|
||||||
Name: name,
|
file.Metadata = map[string]string{
|
||||||
VirtualPath: path,
|
UploadSessionMetaKey: callbackKey,
|
||||||
Mode: fsctx.Nop,
|
|
||||||
Hidden: true,
|
|
||||||
Metadata: map[string]string{
|
|
||||||
UploadSessionMetaKey: callbackKey,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.Use("BeforeUpload", HookValidateFile)
|
fs.Use("BeforeUpload", HookValidateFile)
|
||||||
fs.Use("AfterUpload", HookClearFileHeaderSize)
|
fs.Use("AfterUpload", HookClearFileHeaderSize)
|
||||||
fs.Use("AfterUpload", GenericAfterUpload)
|
fs.Use("AfterUpload", GenericAfterUpload)
|
||||||
|
@ -175,14 +171,15 @@ func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadSession := &serializer.UploadSession{
|
uploadSession := &serializer.UploadSession{
|
||||||
Key: callbackKey,
|
Key: callbackKey,
|
||||||
UID: fs.User.ID,
|
UID: fs.User.ID,
|
||||||
PolicyID: fs.Policy.ID,
|
PolicyID: fs.Policy.ID,
|
||||||
VirtualPath: path,
|
VirtualPath: file.VirtualPath,
|
||||||
Name: name,
|
Name: file.Name,
|
||||||
Size: size,
|
Size: file.Size,
|
||||||
SavePath: file.SavePath,
|
SavePath: file.SavePath,
|
||||||
ChunkSize: fs.Policy.OptionsSerialized.ChunkSize,
|
ChunkSize: fs.Policy.OptionsSerialized.ChunkSize,
|
||||||
|
LastModified: file.GetLastModified(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取上传凭证
|
// 获取上传凭证
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UploadPolicy slave模式下传递的上传策略
|
// UploadPolicy slave模式下传递的上传策略
|
||||||
|
@ -31,14 +32,15 @@ type UploadCredential struct {
|
||||||
|
|
||||||
// UploadSession 上传会话
|
// UploadSession 上传会话
|
||||||
type UploadSession struct {
|
type UploadSession struct {
|
||||||
Key string
|
Key string // 上传会话 GUID
|
||||||
UID uint
|
UID uint // 发起者
|
||||||
PolicyID uint
|
PolicyID uint
|
||||||
VirtualPath string
|
VirtualPath string // 用户文件路径,不含文件名
|
||||||
Name string
|
Name string // 文件名
|
||||||
Size uint64
|
Size uint64 // 文件大小
|
||||||
SavePath string
|
SavePath string // 物理存储路径,包含物理文件名
|
||||||
ChunkSize uint64
|
ChunkSize uint64 // 分块大小,0 为部分快
|
||||||
|
LastModified *time.Time // 可选的文件最后修改日期
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadCallback 上传回调正文
|
// UploadCallback 上传回调正文
|
||||||
|
|
|
@ -504,8 +504,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
// 文件
|
// 文件
|
||||||
file := auth.Group("file", middleware.HashID(hashid.FileID))
|
file := auth.Group("file", middleware.HashID(hashid.FileID))
|
||||||
{
|
{
|
||||||
// 文件上传
|
|
||||||
file.POST("upload", controllers.FileUploadStream)
|
|
||||||
// 创建上传会话
|
// 创建上传会话
|
||||||
file.PUT("upload/session", controllers.GetUploadCredential)
|
file.PUT("upload/session", controllers.GetUploadCredential)
|
||||||
// 更新文件
|
// 更新文件
|
||||||
|
|
|
@ -4,17 +4,20 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UploadSessionService 获取上传凭证服务
|
// UploadSessionService 获取上传凭证服务
|
||||||
type UploadSessionService struct {
|
type UploadSessionService struct {
|
||||||
Path string `json:"path" binding:"required"`
|
Path string `json:"path" binding:"required"`
|
||||||
Size uint64 `json:"size" binding:"min=0"`
|
Size uint64 `json:"size" binding:"min=0"`
|
||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
PolicyID string `json:"policy_id" binding:"required"`
|
PolicyID string `json:"policy_id" binding:"required"`
|
||||||
|
LastModified int64 `json:"last_modified"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 创建新的上传会话
|
// Create 创建新的上传会话
|
||||||
|
@ -35,7 +38,16 @@ func (service *UploadSessionService) Create(ctx context.Context, c *gin.Context)
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, "存储策略发生变化,请刷新文件列表并重新添加此任务", nil)
|
return serializer.Err(serializer.CodePolicyNotAllowed, "存储策略发生变化,请刷新文件列表并重新添加此任务", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
credential, err := fs.CreateUploadSession(ctx, service.Path, service.Size, service.Name)
|
file := &fsctx.FileStream{
|
||||||
|
Size: service.Size,
|
||||||
|
Name: service.Name,
|
||||||
|
VirtualPath: service.Path,
|
||||||
|
}
|
||||||
|
if service.LastModified > 0 {
|
||||||
|
lastModified := time.UnixMilli(service.LastModified)
|
||||||
|
file.LastModified = &lastModified
|
||||||
|
}
|
||||||
|
credential, err := fs.CreateUploadSession(ctx, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue