125 lines
2.8 KiB
Go
125 lines
2.8 KiB
Go
|
|
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 d’un 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,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|