FloorVisualizer/internal/handler/upload_handler.go

70 lines
1.5 KiB
Go
Raw Normal View History

package handler
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
func handleUpload(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeErr(w, 405, "Method not allowed")
return
}
if err := r.ParseMultipartForm(20 << 20); err != nil {
writeErr(w, 400, "image too large (max 20MB)")
return
}
file, _, err := r.FormFile("image")
if err != nil {
writeErr(w, 400, "missing image file")
return
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil || len(data) == 0 {
writeErr(w, 400, "failed to read image")
return
}
ct := http.DetectContentType(data)
if !strings.HasPrefix(ct, "image/") {
writeErr(w, 400, "file is not an image")
return
}
hash := sha256.Sum256(data)
name := hex.EncodeToString(hash[:])[:16] + "_" + fmt.Sprintf("%d", time.Now().UnixNano())
dir := "static/images"
os.MkdirAll(dir, 0755)
// Determine extension from content type
ext := ".jpg"
switch {
case strings.Contains(ct, "png"):
ext = ".png"
case strings.Contains(ct, "webp"):
ext = ".webp"
case strings.Contains(ct, "gif"):
ext = ".gif"
case strings.Contains(ct, "svg"):
ext = ".svg"
}
filePath := filepath.Join(dir, name+ext)
if err := os.WriteFile(filePath, data, 0644); err != nil {
writeErr(w, 500, "failed to save image")
return
}
url := "/static/images/" + name + ext
writeJSON(w, 200, map[string]string{"url": url, "filename": name + ext})
}