All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 5m12s
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
var allowedExtensions = map[string]bool{
|
|
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
|
|
".mp4": true, ".webm": true, ".mp3": true, ".ogg": true,
|
|
".pdf": true, ".txt": true,
|
|
}
|
|
|
|
func (store *Store) UploadMessageFile(ctx *gin.Context) {
|
|
file, err := ctx.FormFile("file")
|
|
if err != nil {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
|
|
return
|
|
}
|
|
|
|
const maxSize = 10 << 20 // 10MB
|
|
if file.Size > maxSize {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{"error": "file too large"})
|
|
return
|
|
}
|
|
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
if !allowedExtensions[ext] {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{"error": "file type not allowed"})
|
|
return
|
|
}
|
|
|
|
b := make([]byte, 16)
|
|
if _, err := rand.Read(b); err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate filename"})
|
|
return
|
|
}
|
|
filename := hex.EncodeToString(b) + ext
|
|
|
|
uploadDir := "/backend/uploads"
|
|
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create upload directory"})
|
|
return
|
|
}
|
|
|
|
dest := filepath.Join(uploadDir, filename)
|
|
if err := ctx.SaveUploadedFile(file, dest); err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save file"})
|
|
return
|
|
}
|
|
if err := os.Chmod(dest, 0644); err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "failed to set file permissions"})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, gin.H{"url": "/uploads/" + filename})
|
|
}
|