From 1ff4d5997848df7a8373d7ff93adabe28eb787bd Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Tue, 28 Jan 2020 13:40:19 +0800 Subject: [PATCH] Feat: preview shared file --- routers/controllers/share.go | 24 +++++++++++++++++ routers/controllers/user.go | 6 +++++ routers/router.go | 7 ++++- service/explorer/file.go | 5 ++++ service/share/visit.go | 51 +++++++++++++++++++++++++++++++----- 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/routers/controllers/share.go b/routers/controllers/share.go index 6845f5a..6d18bf8 100644 --- a/routers/controllers/share.go +++ b/routers/controllers/share.go @@ -1,6 +1,7 @@ package controllers import ( + "context" "github.com/HFO4/cloudreve/service/share" "github.com/gin-gonic/gin" ) @@ -37,3 +38,26 @@ func GetShareDownload(c *gin.Context) { c.JSON(200, ErrorResponse(err)) } } + +// PreviewShare 预览分享文件内容 +func PreviewShare(c *gin.Context) { + // 创建上下文 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var service share.SingleFileService + if err := c.ShouldBindUri(&service); err == nil { + res := service.PreviewContent(ctx, c, false) + // 是否需要重定向 + if res.Code == -301 { + c.Redirect(301, res.Data.(string)) + return + } + // 是否有错误发生 + if res.Code != 0 { + c.JSON(200, res) + } + } else { + c.JSON(200, ErrorResponse(err)) + } +} diff --git a/routers/controllers/user.go b/routers/controllers/user.go index 268b296..0e75ffe 100644 --- a/routers/controllers/user.go +++ b/routers/controllers/user.go @@ -116,6 +116,12 @@ func UserLogin(c *gin.Context) { } +// UserSignOut 用户退出登录 +func UserSignOut(c *gin.Context) { + util.DeleteSession(c, "user_id") + c.JSON(200, serializer.Response{}) +} + // UserMe 获取当前登录的用户 func UserMe(c *gin.Context) { currUser := CurrentUser(c) diff --git a/routers/router.go b/routers/router.go index a2c1d1e..00aa1bd 100644 --- a/routers/router.go +++ b/routers/router.go @@ -171,9 +171,11 @@ func InitMasterRouter() *gin.Engine { share := v3.Group("share") { // 获取分享 - share.GET(":id", controllers.GetShare) + share.GET("info/:id", controllers.GetShare) // 创建文件下载会话 share.POST("download/:id", controllers.GetShareDownload) + // 预览分享文件 + share.GET("preview/:id", controllers.PreviewShare) } // 需要登录保护的 @@ -185,7 +187,10 @@ func InitMasterRouter() *gin.Engine { { // 当前登录用户信息 user.GET("me", controllers.UserMe) + // 存储信息 user.GET("storage", controllers.UserStorage) + // 退出登录 + user.DELETE("session", controllers.UserSignOut) // WebAuthn 注册相关 authn := user.Group("authn") diff --git a/service/explorer/file.go b/service/explorer/file.go index 40c00d0..065950d 100644 --- a/service/explorer/file.go +++ b/service/explorer/file.go @@ -218,6 +218,11 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con } defer fs.Recycle() + // 如果上下文中已有File对象,则重设目标 + if file, ok := ctx.Value(fsctx.FileModelCtx).(*model.File); ok { + fs.SetTargetFile(&[]model.File{*file}) + } + // 获取文件预览响应 resp, err := fs.Preview(ctx, service.Path, isText) if err != nil { diff --git a/service/share/visit.go b/service/share/visit.go index e622fb6..b8612e9 100644 --- a/service/share/visit.go +++ b/service/share/visit.go @@ -5,8 +5,10 @@ import ( "fmt" model "github.com/HFO4/cloudreve/models" "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/HFO4/cloudreve/service/explorer" "github.com/gin-gonic/gin" ) @@ -66,13 +68,7 @@ func (service *SingleFileService) CreateDownloadSession(c *gin.Context) serializ } // 检查用户是否可以下载此分享的文件 - err := share.CanBeDownloadBy(user) - if err != nil { - return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil) - } - - // 对积分、下载次数进行更新 - err = share.DownloadBy(user) + err := CheckBeforeGetShare(share, user) if err != nil { return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil) } @@ -101,3 +97,44 @@ func (service *SingleFileService) CreateDownloadSession(c *gin.Context) serializ Data: downloadURL, } } + +// PreviewContent 预览文件,需要登录会话, isText - 是否为文本文件,文本文件会 +// 强制经由服务端中转 +func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Context, isText bool) serializer.Response { + user := currentUser(c) + share := model.GetShareByHashID(c.Param("id")) + if share == nil || !share.IsAvailable() { + return serializer.Err(serializer.CodeNotFound, "分享不存在或已被取消", nil) + } + + // 检查用户是否可以下载此分享的文件 + err := CheckBeforeGetShare(share, user) + if err != nil { + return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil) + } + + // 用于调用子service + ctx = context.WithValue(ctx, fsctx.FileModelCtx, share.GetSource()) + subService := explorer.SingleFileService{ + Path: "", + } + + return subService.PreviewContent(ctx, c, isText) +} + +// CheckBeforeGetShare 获取分享内容/下载前进行的一系列检查 +func CheckBeforeGetShare(share *model.Share, user *model.User) error { + // 检查用户是否可以下载此分享的文件 + err := share.CanBeDownloadBy(user) + if err != nil { + return err + } + + // 对积分、下载次数进行更新 + err = share.DownloadBy(user) + if err != nil { + return err + } + + return nil +}