202 lines
4.6 KiB
Go
202 lines
4.6 KiB
Go
|
|
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)
|
||
|
|
}
|