Feat: support setting "last modified" props when creating upload session

pull/1107/head
HFO4 2 years ago
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…
Cancel
Save