feat(backend): implement statistics tracking for file uploads, shares, and downloads

This commit is contained in:
keven
2025-10-19 16:34:17 +08:00
parent 84c104be90
commit b4f577e758
4 changed files with 98 additions and 2 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
"github.com/spf13/cast"
)
type DownloadShareClaims struct {
@@ -88,10 +89,11 @@ func VaildateShare(c echo.Context) error {
if shareInfo.ViewNum < 1 {
return utils.HTTPErrorHandler(c, errors.New("下载次数不足"))
}
downloadWindow := utils.GetEnvWithDefault("share.download_window", "12")
token := jwt.NewWithClaims(jwt.SigningMethodHS256, DownloadShareClaims{
ShareId: r.ShareId,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(60 * time.Minute)),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(cast.ToDuration(downloadWindow + "h"))),
},
})
@@ -121,6 +123,21 @@ func VaildateShare(c echo.Context) error {
models.SetRedisShareInfo(r.ShareId, models.RedisShareInfo{
ViewNum: latestViewNum,
})
// 统计分享数
currentDate := time.Now().Format("2006-01-02")
statData, _ := models.GetRedisStat(currentDate)
if statData == nil {
statData = &models.StatData{
FileSize: 0,
FileNum: 0,
ShareNum: 0,
DownloadNum: 0,
}
}
statData.DownloadNum += 1
models.SetRedisStat(currentDate, *statData)
if shareInfo.Type == models.ShareTypeFile {
return utils.HTTPSuccessHandler(c, map[string]any{
"token": downloadToken,

View File

@@ -222,6 +222,20 @@ func FinishUploadTask(c echo.Context) error {
models.SetRedisFileInfo(r.FileId, models.RedisFileInfo{
FileType: models.FileTypeUpload,
})
// 统计
currentDate := time.Now().Format("2006-01-02")
statData, _ := models.GetRedisStat(currentDate)
if statData == nil {
statData = &models.StatData{
FileSize: 0,
FileNum: 0,
ShareNum: 0,
DownloadNum: 0,
}
}
statData.FileSize += fileInfo.FileSize
statData.FileNum += 1
models.SetRedisStat(currentDate, *statData)
return utils.HTTPSuccessHandler(c, map[string]any{
"size": fileInfo.FileSize,

View File

@@ -12,6 +12,7 @@ import (
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/spf13/cast"
)
type CreateShareProps struct {
@@ -111,12 +112,29 @@ func CreateShareInfo(c echo.Context) error {
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
_, err = client.Enqueue(asynq.NewTask("share:remove", json), asynq.ProcessIn(time.Duration(r.Config.ExpireAt)*time.Minute))
// 这里延时分享过期时间基础上加下载窗口期后1小时删除防止用户过期前几分钟才开始下载下载一半文件不见了
downloadWindow := utils.GetEnvWithDefault("share.download_window", "12")
deleteTime := time.Duration(r.Config.ExpireAt)*time.Minute + cast.ToDuration(downloadWindow+"h") + 1*time.Hour
_, err = client.Enqueue(asynq.NewTask("share:remove", json), asynq.ProcessIn(deleteTime))
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
}
// 统计分享数
currentDate := time.Now().Format("2006-01-02")
statData, _ := models.GetRedisStat(currentDate)
if statData == nil {
statData = &models.StatData{
FileSize: 0,
FileNum: 0,
ShareNum: 0,
DownloadNum: 0,
}
}
statData.ShareNum += 1
models.SetRedisStat(currentDate, *statData)
return utils.HTTPSuccessHandler(c, map[string]any{
"id": id,
"file_name": r.FileName,

View File

@@ -0,0 +1,47 @@
package models
import (
"backend/internal/utils"
"encoding/json"
"dario.cat/mergo"
"github.com/redis/go-redis/v9"
)
// 统计数据结构
type StatData struct {
FileSize int64 `json:"file_size"` // 文件大小
FileNum int64 `json:"file_num"` // 文件数量
ShareNum int64 `json:"share_num"` // 分享数量
DownloadNum int64 `json:"download_num"` // 下载数量
}
func GetRedisStat(key string) (*StatData, error) {
rdb, ctx := utils.GetRedisClient()
statUnmarshalData, err := rdb.HGet(ctx, "015:stat", key).Result()
if err == redis.Nil {
return nil, nil
}
if err != nil {
return nil, err
}
var stat StatData
if err := json.Unmarshal([]byte(statUnmarshalData), &stat); err != nil {
return nil, err
}
return &stat, nil
}
func SetRedisStat(key string, stat StatData) error {
rdb, ctx := utils.GetRedisClient()
old_stat, err := GetRedisStat(key)
if err != nil {
return err
}
if old_stat != nil {
mergo.Merge(&stat, old_stat)
}
jsonData, _ := json.Marshal(stat)
_, err = rdb.HSet(ctx, "015:stat", key, string(jsonData)).Result()
return err
}