shelfy-v2/internal/controllers/folder_stats.go

125 lines
2.8 KiB
Go
Raw Normal View History

2025-09-28 11:42:05 +00:00
package controllers
import (
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
)
type FolderStat struct {
Name string `json:"Name"`
Path string `json:"Path"`
Size int64 `json:"Size"`
IsDir bool `json:"IsDir"`
Children []FolderStat `json:"Children,omitempty"`
}
type SystemStats struct {
CPUUsage float64 `json:"CPUUsage"`
TotalRAM uint64 `json:"TotalRAM"`
UsedRAM uint64 `json:"UsedRAM"`
FreeRAM uint64 `json:"FreeRAM"`
UsedRAMPct float64 `json:"UsedRAMPct"`
DiskTotal uint64 `json:"DiskTotal"`
DiskFree uint64 `json:"DiskFree"`
DiskUsed uint64 `json:"DiskUsed"`
DiskUsedPct float64 `json:"DiskUsedPct"`
}
// calcule récursivement la taille dun dossier
func getFolderStats(absPath, relPath string) (FolderStat, error) {
info, err := os.Stat(absPath)
if err != nil {
return FolderStat{}, err
}
stat := FolderStat{
Name: info.Name(),
Path: relPath,
IsDir: info.IsDir(),
Size: 0,
}
if !info.IsDir() {
stat.Size = info.Size()
return stat, nil
}
entries, err := os.ReadDir(absPath)
if err != nil {
return stat, err
}
var total int64
for _, entry := range entries {
childAbs := filepath.Join(absPath, entry.Name())
childRel := filepath.Join(relPath, entry.Name())
childStat, err := getFolderStats(childAbs, childRel)
if err != nil {
continue
}
stat.Children = append(stat.Children, childStat)
total += childStat.Size
}
stat.Size = total
return stat, nil
}
// Handler principal
func FolderStatsHandler() gin.HandlerFunc {
return func(c *gin.Context) {
base := "upload"
rel := c.Query("path")
if rel == "" {
rel = ""
}
rel = filepath.Clean("/" + rel)
rel = strings.TrimPrefix(rel, "/")
absPath := filepath.Join(base, rel)
baseAbs, _ := filepath.Abs(base)
absPath, _ = filepath.Abs(absPath)
if !strings.HasPrefix(absPath, baseAbs) {
c.JSON(http.StatusForbidden, gin.H{"error": "Chemin invalide"})
return
}
// stats dossier
folderStats, err := getFolderStats(absPath, rel)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de calculer les stats"})
return
}
// stats système
cpuPercent, _ := cpu.Percent(0, false)
memStats, _ := mem.VirtualMemory()
diskStats, _ := disk.Usage(baseAbs)
sysStats := SystemStats{
CPUUsage: cpuPercent[0],
TotalRAM: memStats.Total,
UsedRAM: memStats.Used,
FreeRAM: memStats.Available,
UsedRAMPct: memStats.UsedPercent,
DiskTotal: diskStats.Total,
DiskFree: diskStats.Free,
DiskUsed: diskStats.Used,
DiskUsedPct: diskStats.UsedPercent,
}
// réponse
c.JSON(http.StatusOK, gin.H{
"folderStats": folderStats,
"systemStats": sysStats,
})
}
}