package controller import ( "net/http" "strconv" "seeyon-filesystem/dto" "seeyon-filesystem/middleware" "seeyon-filesystem/service" "seeyon-filesystem/utils" "github.com/gin-gonic/gin" ) // ShareController 分享控制器 type ShareController struct { shareService *service.ShareService fileService *service.FileService } // NewShareController 创建分享控制器实例 func NewShareController() *ShareController { return &ShareController{ shareService: service.NewShareService(), fileService: service.NewFileService(), } } // Create 创建分享 // POST /api/share func (c *ShareController) Create(ctx *gin.Context) { ownerID := middleware.GetCurrentUserID(ctx) var req dto.ShareCreateRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.BadRequest(ctx, "参数错误: "+err.Error()) return } result, err := c.shareService.Create(&req, ownerID) if err != nil { utils.ServerError(ctx, err.Error()) return } utils.Success(ctx, result) } // ListMyShares 查看我的分享 // GET /api/share func (c *ShareController) ListMyShares(ctx *gin.Context) { ownerID := middleware.GetCurrentUserID(ctx) results, err := c.shareService.ListByOwner(ownerID) if err != nil { utils.ServerError(ctx, err.Error()) return } utils.Success(ctx, results) } // Cancel 取消分享 // DELETE /api/share/:id func (c *ShareController) Cancel(ctx *gin.Context) { ownerID := middleware.GetCurrentUserID(ctx) id, err := strconv.ParseUint(ctx.Param("id"), 10, 64) if err != nil { utils.BadRequest(ctx, "无效的分享ID") return } if err := c.shareService.Cancel(id, ownerID); err != nil { utils.ServerError(ctx, err.Error()) return } utils.SuccessWithMessage(ctx, "已取消分享", nil) } // GetShareInfo 获取分享信息(公开) // GET /api/s/:code func (c *ShareController) GetShareInfo(ctx *gin.Context) { code := ctx.Param("code") fileInfo, share, err := c.shareService.GetByCode(code) if err != nil { utils.NotFound(ctx, err.Error()) return } utils.Success(ctx, gin.H{ "file": fileInfo, "has_password": share.Password != "", "expire_at": share.ExpireAt, }) } // VerifySharePassword 验证分享密码 // POST /api/s/:code/verify func (c *ShareController) VerifySharePassword(ctx *gin.Context) { code := ctx.Param("code") var req dto.ShareVerifyRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.BadRequest(ctx, "请输入密码") return } _, share, err := c.shareService.GetByCode(code) if err != nil { utils.NotFound(ctx, err.Error()) return } if !c.shareService.VerifyPassword(share.ID, req.Password) { utils.Unauthorized(ctx, "密码错误") return } utils.Success(ctx, gin.H{"verified": true}) } // DownloadShareFile 下载分享文件 // GET /api/s/:code/download func (c *ShareController) DownloadShareFile(ctx *gin.Context) { code := ctx.Param("code") _, share, err := c.shareService.GetByCode(code) if err != nil { utils.NotFound(ctx, err.Error()) return } // 检查下载权限 if share.AllowDownload != 1 { utils.Forbidden(ctx, "此分享不允许下载") return } // 验证密码 if share.Password != "" { password := ctx.Query("password") if !c.shareService.VerifyPassword(share.ID, password) { utils.Unauthorized(ctx, "需要密码") return } } reader, file, err := c.fileService.DownloadByFileID(share.FileID) if err != nil { utils.ServerError(ctx, err.Error()) return } defer reader.Close() ctx.Header("Content-Disposition", "attachment; filename=\""+file.Name+"\"") ctx.Header("Content-Type", file.MimeType) ctx.DataFromReader(http.StatusOK, file.Size, file.MimeType, reader, nil) } // PreviewShareFile 预览分享文件(内联展示) // GET /api/s/:code/preview func (c *ShareController) PreviewShareFile(ctx *gin.Context) { code := ctx.Param("code") _, share, err := c.shareService.GetByCode(code) if err != nil { utils.NotFound(ctx, err.Error()) return } // 检查预览权限 if share.AllowPreview != 1 { utils.Forbidden(ctx, "此分享不允许预览") return } // 验证密码 if share.Password != "" { password := ctx.Query("password") if !c.shareService.VerifyPassword(share.ID, password) { utils.Unauthorized(ctx, "需要密码") return } } reader, file, err := c.fileService.DownloadByFileID(share.FileID) if err != nil { utils.ServerError(ctx, err.Error()) return } defer reader.Close() // 内联展示 ctx.Header("Content-Disposition", "inline; filename=\""+file.Name+"\"") ctx.Header("Content-Type", file.MimeType) ctx.Header("Content-Length", strconv.FormatInt(file.Size, 10)) ctx.DataFromReader(http.StatusOK, file.Size, file.MimeType, reader, nil) }