forked from tildetown/town
108 lines
2.1 KiB
Go
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]
|
|
}
|