Files
ci/internal/handler/upload.go
2026-06-18 21:19:47 +08:00

77 lines
1.9 KiB
Go

package handler
import (
"fmt"
"net/http"
"path/filepath"
"strings"
"ci/internal/service"
"github.com/gin-gonic/gin"
)
// UploadHandler handles file upload endpoints.
type UploadHandler struct {
Svc *service.ProjectService
}
func NewUploadHandler(svc *service.ProjectService) *UploadHandler {
return &UploadHandler{Svc: svc}
}
// UploadFiles handles source file upload for a project (zip/tar.gz).
func (h *UploadHandler) UploadFiles(c *gin.Context) {
id, err := parseID(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project id"})
return
}
// Verify project exists and is upload mode
project, err := h.Svc.GetProject(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
return
}
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "no file provided"})
return
}
// Validate file extension
ext := strings.ToLower(filepath.Ext(file.Filename))
valid := false
if ext == ".zip" {
valid = true
}
if strings.HasSuffix(strings.ToLower(file.Filename), ".tar.gz") || strings.HasSuffix(strings.ToLower(file.Filename), ".tgz") {
valid = true
}
if !valid {
c.JSON(http.StatusBadRequest, gin.H{"error": "only .zip and .tar.gz files are supported"})
return
}
// Save uploaded file to temp location
tmpPath := filepath.Join(h.Svc.Workspace.ProjectDir(project.ID), file.Filename)
if err := c.SaveUploadedFile(file, tmpPath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to save file: %v", err)})
return
}
// Extract to src directory
if err := h.Svc.Workspace.ExtractArchive(project.ID, tmpPath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to extract: %v", err)})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "file uploaded and extracted successfully",
"filename": file.Filename,
})
}