Files
015/backend/internal/controllers/download.go

124 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controllers
import (
"backend/internal/models"
"backend/internal/utils"
"backend/middleware"
"errors"
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
)
type DownloadShareClaims struct {
ShareId string `json:"share_id"`
jwt.RegisteredClaims
}
func DownloadShare(c echo.Context) error {
cc := c.(*middleware.CustomContext)
token := cc.FormValue("token")
if token == "" {
return utils.HTTPErrorHandler(c, errors.New("缺少token"))
}
claims := DownloadShareClaims{}
t, err := jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
return []byte(utils.GetEnv("download_secret")), nil
})
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
if !t.Valid {
return utils.HTTPErrorHandler(c, errors.New("token格式错误"))
}
shareInfo, _ := models.GetRedisShareInfo(claims.ShareId)
if shareInfo.Type == models.ShareTypeFile {
fileInfo, _ := models.GetRedisFileInfo(shareInfo.Data)
uploadPath, err := utils.GetUploadDirPath()
if err != nil {
return err
}
return cc.Attachment(fmt.Sprintf("%s/%s", uploadPath, utils.GetFileId(fileInfo.FileHash, fileInfo.FileSize)), shareInfo.FileName)
}
return utils.HTTPSuccessHandler(c, map[string]any{
"data": shareInfo.Data,
})
}
type VaildateShareProps struct {
ShareId string `json:"share_id"`
Password string `json:"password"`
}
func VaildateShare(c echo.Context) error {
cc := c.(*middleware.CustomContext)
r := new(VaildateShareProps)
if err := cc.Bind(r); err != nil {
return utils.HTTPErrorHandler(c, err)
}
if r.ShareId == "" {
return utils.HTTPErrorHandler(c, errors.New("缺少分享ID"))
}
shareInfo, err := models.GetRedisShareInfo(r.ShareId)
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
if shareInfo == nil {
return utils.HTTPErrorHandler(c, errors.New("分享不存在"))
}
if shareInfo.Password != "" && shareInfo.Password != r.Password {
return utils.HTTPErrorHandler(c, errors.New("分享密码错误"))
}
// 如果下载次数为0则设置为-1 防止空值问题
if shareInfo.ViewNum < 1 {
return utils.HTTPErrorHandler(c, errors.New("下载次数不足"))
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, DownloadShareClaims{
ShareId: r.ShareId,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(60 * time.Minute)),
},
})
// Sign and get the complete encoded token as a string using the secret
downloadToken, err := token.SignedString([]byte(utils.GetEnv("download_secret")))
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
if shareInfo.Type == models.ShareTypeFile {
fileInfo, err := models.GetRedisFileInfo(shareInfo.Data)
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
if fileInfo == nil {
return utils.HTTPErrorHandler(c, errors.New("分享文件不存在"))
}
if fileInfo.FileType != models.FileTypeUpload {
return utils.HTTPErrorHandler(c, errors.New("分享文件状态错误"))
}
}
// download_nums 必须放在创建token的时候减掉不然多线程下载会导致多次减掉
latestViewNum := shareInfo.ViewNum - 1
// 如果下载次数为0则设置为-1 防止空值问题
if latestViewNum < 1 {
latestViewNum = -1
}
models.SetRedisShareInfo(r.ShareId, models.RedisShareInfo{
ViewNum: latestViewNum,
})
if shareInfo.Type == models.ShareTypeFile {
return utils.HTTPSuccessHandler(c, map[string]any{
"token": downloadToken,
})
}
return utils.HTTPSuccessHandler(c, map[string]any{
"token": downloadToken,
})
}