diff --git a/models/group.go b/models/group.go index d9f3a06..b1b5ffe 100644 --- a/models/group.go +++ b/models/group.go @@ -27,6 +27,7 @@ type Group struct { type GroupOption struct { ArchiveDownloadEnabled bool `json:"archive_download"` ArchiveTaskEnabled bool `json:"archive_task"` + OneTimeDownloadEnabled bool `json:"one_time_download"` } // GetAria2Option 获取用户离线下载设备 diff --git a/pkg/filesystem/archive.go b/pkg/filesystem/archive.go index 0c4b254..84b1ed7 100644 --- a/pkg/filesystem/archive.go +++ b/pkg/filesystem/archive.go @@ -38,13 +38,16 @@ func (fs *FileSystem) Compress(ctx context.Context, folderIDs, fileIDs []uint) ( } // 创建临时压缩文件 - zipFilePath := filepath.Join(model.GetSettingByName("temp_path"), fmt.Sprintf("archive_%d.zip", time.Now().UnixNano())) + zipFilePath := filepath.Join( + model.GetSettingByName("temp_path"), + fmt.Sprintf("archive_%d.zip", time.Now().UnixNano()), + ) zipFile, err := util.CreatNestedFile(zipFilePath) - defer zipFile.Close() if err != nil { util.Log().Warning("%s", err) return "", err } + defer zipFile.Close() // 创建压缩文件Writer zipWriter := zip.NewWriter(zipFile) diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index 1ab7369..acb47a0 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -2,7 +2,6 @@ package filesystem import ( "context" - "errors" "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/filesystem/local" "github.com/HFO4/cloudreve/pkg/filesystem/response" @@ -121,10 +120,11 @@ func (fs *FileSystem) dispatchHandler() error { } // NewFileSystemFromContext 从gin.Context创建文件系统 +// TODO 用户不存在时使用匿名文件系统 func NewFileSystemFromContext(c *gin.Context) (*FileSystem, error) { user, exist := c.Get("user") if !exist { - return nil, errors.New("无法找到用户") + return NewAnonymousFileSystem() } fs, err := NewFileSystem(user.(*model.User)) return fs, err diff --git a/pkg/serializer/user.go b/pkg/serializer/user.go index 59d5279..687e646 100644 --- a/pkg/serializer/user.go +++ b/pkg/serializer/user.go @@ -40,6 +40,7 @@ type group struct { AllowShare bool `json:"allowShare"` AllowRemoteDownload bool `json:"allowRemoteDownload"` AllowTorrentDownload bool `json:"allowTorrentDownload"` + AllowArchiveDownload bool `json:"allowArchiveDownload"` } type storage struct { @@ -72,6 +73,7 @@ func BuildUser(user model.User) User { AllowShare: user.Group.ShareEnabled, AllowRemoteDownload: aria2Option[0], AllowTorrentDownload: aria2Option[2], + AllowArchiveDownload: user.Group.OptionsSerialized.ArchiveDownloadEnabled, }, } } diff --git a/routers/router.go b/routers/router.go index 46219df..d5138c2 100644 --- a/routers/router.go +++ b/routers/router.go @@ -4,7 +4,6 @@ import ( "github.com/HFO4/cloudreve/middleware" "github.com/HFO4/cloudreve/pkg/conf" "github.com/HFO4/cloudreve/routers/controllers" - "github.com/gin-contrib/cors" "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" ) @@ -19,13 +18,13 @@ func InitRouter() *gin.Engine { */ r.Use(middleware.Session(conf.SystemConfig.SessionSecret)) - // CORS TODO: 根据配置文件来 - r.Use(cors.New(cors.Config{ - AllowOrigins: []string{"http://localhost:3000"}, - AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"}, - AllowHeaders: []string{"Cookie", "Content-Length", "Content-Type", "X-Path", "X-FileName"}, - AllowCredentials: true, - })) + //// CORS TODO: 根据配置文件来 + //r.Use(cors.New(cors.Config{ + // AllowOrigins: []string{"http://localhost:3000"}, + // AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"}, + // AllowHeaders: []string{"Cookie", "Content-Length", "Content-Type", "X-Path", "X-FileName"}, + // AllowCredentials: true, + //})) // 测试模式加入Mock助手中间件 if gin.Mode() == gin.TestMode { @@ -67,8 +66,10 @@ func InitRouter() *gin.Engine { { file := sign.Group("file") { - // 下載文件 + // 文件外链 file.GET("get/:id/:name", controllers.AnonymousGetContent) + // 下載已经打包好的文件 + file.GET("archive/:id/archive.zip", controllers.DownloadArchive) } } @@ -104,8 +105,6 @@ func InitRouter() *gin.Engine { file.GET("source/:id", controllers.GetSource) // 打包要下载的文件 file.POST("archive", controllers.Archive) - // 下載已经打包好的文件 - file.Use(middleware.SignRequired()).GET("archive/:id", controllers.DownloadArchive) } // 目录 diff --git a/service/explorer/file.go b/service/explorer/file.go index 140538b..be08ef6 100644 --- a/service/explorer/file.go +++ b/service/explorer/file.go @@ -6,11 +6,9 @@ import ( "github.com/HFO4/cloudreve/pkg/filesystem" "github.com/HFO4/cloudreve/pkg/filesystem/fsctx" "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/HFO4/cloudreve/pkg/util" "github.com/gin-gonic/gin" "io" "net/http" - "os" "time" ) @@ -48,21 +46,20 @@ func (service *ArchiveDownloadService) Download(ctx context.Context, c *gin.Cont return serializer.Err(serializer.CodeNotSet, err.Error(), err) } + if fs.User.Group.OptionsSerialized.OneTimeDownloadEnabled { + // 清理资源,删除临时文件 + _ = cache.Deletes([]string{service.ID}, "archive_") + } + + c.Header("Content-Disposition", "attachment;") c.Header("Content-Type", "application/zip") - http.ServeContent(c.Writer, c.Request, "archive.zip", time.Now(), rs) + http.ServeContent(c.Writer, c.Request, "", time.Now(), rs) // 检查是否需要关闭文件 if fc, ok := rs.(io.Closer); ok { err = fc.Close() } - // 清理资源,删除临时文件 - _ = cache.Deletes([]string{service.ID}, "archive_") - err = os.Remove(zipPath.(string)) - if err != nil { - util.Log().Warning("无法删除临时文件 %s :%s", zipPath, err) - } - return serializer.Response{ Code: 0, } diff --git a/service/explorer/objects.go b/service/explorer/objects.go index b87bef0..5aa56ec 100644 --- a/service/explorer/objects.go +++ b/service/explorer/objects.go @@ -61,13 +61,13 @@ func (service *ItemService) Archive(ctx context.Context, c *gin.Context) seriali } zipID := util.RandStringRunes(16) signedURI, err := auth.SignURI( - fmt.Sprintf("/api/v3/file/archive/%s", zipID), - time.Now().Unix()+120, + fmt.Sprintf("/api/v3/file/archive/%s/archive.zip", zipID), + time.Now().Unix()+30, ) finalURL := siteURL.ResolveReference(signedURI).String() // 将压缩文件记录存入缓存 - err = cache.Set("archive_"+zipID, zipFile, 120) + err = cache.Set("archive_"+zipID, zipFile, 30) if err != nil { return serializer.Err(serializer.CodeIOFailed, "无法写入缓存", err) }