shelfy-v2/internal/controllers/folder_stats.go
2025-09-28 13:42:05 +02:00

125 lines
2.8 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 (
"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,
})
}
}