town/share/main.go
2025-04-22 18:03:19 +00:00

108 lines
2.1 KiB
Go

package main
import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
const (
UPLOAD_DIR = "./uploads"
MAX_FILE_SIZE = 10 << 20
)
func main() {
if err := os.MkdirAll(UPLOAD_DIR, 0755); err != nil {
panic(fmt.Sprintf("Failed to create upload directory: %v", err))
}
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/", homeHandler)
router.POST("/upload", uploadHandler)
router.Static("/static", "./static")
router.Run(":8787")
}
func homeHandler(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "town share",
})
}
func uploadHandler(c *gin.Context) {
file, header, err := c.Request.FormFile("image")
if err != nil {
renderError(c, "melancholy")
return
}
defer file.Close()
if header.Size > MAX_FILE_SIZE {
renderError(c, "max size is 10mb")
return
}
contentType := header.Header.Get("Content-Type")
if !isValidImageType(contentType) {
renderError(c, "only jpg, png, and gif are supported")
return
}
// TODO tweak this
extension := filepath.Ext(header.Filename)
uniqueFilename := fmt.Sprintf("%s-%s%s",
uuid.New().String(),
time.Now().Format("20060102-150405"),
extension,
)
destPath := filepath.Join(UPLOAD_DIR, uniqueFilename)
dest, err := os.Create(destPath)
if err != nil {
renderError(c, "Failed to save file")
return
}
defer dest.Close()
if _, err := io.Copy(dest, file); err != nil {
renderError(c, "Failed to save file")
return
}
// TODO global const for title
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "town share",
"success": fmt.Sprintf("file uploaded successfully as %s", uniqueFilename),
})
}
// renderError renders the home page with an error message
func renderError(c *gin.Context, message string) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "town share",
"error": message,
})
}
// isValidImageType checks if the content type is a supported image format
func isValidImageType(contentType string) bool {
validTypes := map[string]bool{
"image/jpeg": true,
"image/jpg": true,
"image/png": true,
"image/gif": true,
}
return validTypes[contentType]
}