Files

202 lines
4.6 KiB
Go
Raw Permalink Normal View History

2026-07-03 15:58:29 +08:00
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)
}