picture-uploader/go/main.go

208 lines
5.8 KiB
Go
Raw Normal View History

2024-01-11 22:23:10 +01:00
package main
import (
"fmt"
2024-03-08 14:59:31 +01:00
"html/template"
2024-01-11 22:23:10 +01:00
"io"
2024-01-11 22:38:55 +01:00
"log"
2024-01-11 22:23:10 +01:00
"net/http"
"os"
2024-03-08 14:59:31 +01:00
"strings"
2024-01-11 22:38:55 +01:00
"sync"
"time"
)
var (
lastUploadTime time.Time
mu sync.Mutex
uploadInterval = 10 * time.Second
2024-01-11 22:23:10 +01:00
)
func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/upload", uploadHandler)
2024-03-08 15:32:44 +01:00
http.HandleFunc("/image/", imageHandler)
2024-03-08 15:01:49 +01:00
http.HandleFunc("/view/", viewHandler)
2024-01-11 22:23:10 +01:00
fmt.Println("Server listening on :8080")
http.ListenAndServe(":8080", nil)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
2024-03-08 15:01:49 +01:00
// Setzen der Content Security Policy
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';")
2024-03-08 14:59:31 +01:00
// Verwenden von html/template zur sicheren Ausgabe von HTML
2024-03-08 15:01:49 +01:00
tmpl, err := template.ParseFiles("templates/homeTemplate.html")
2024-03-08 14:59:31 +01:00
if err != nil {
2024-03-08 15:01:49 +01:00
http.Error(w, "Fehler beim Laden des Templates", http.StatusInternalServerError)
return
}
data := struct {
Title string
}{
Title: "Bildupload",
}
err = tmpl.Execute(w, data)
if err != nil {
http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError)
2024-03-08 14:59:31 +01:00
}
2024-01-11 22:23:10 +01:00
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
2024-01-11 22:38:55 +01:00
mu.Lock()
defer mu.Unlock()
if time.Since(lastUploadTime) < uploadInterval {
http.Error(w, "Nur alle 10 Sekunden erlaubt", http.StatusTooManyRequests)
log.Printf("Bildupload zu häufig. Nur alle 10 Sekunden erlaubt.")
return
}
2024-01-11 22:23:10 +01:00
if r.Method == http.MethodPost {
file, handler, err := r.FormFile("image")
if err != nil {
http.Error(w, "Fehler beim Lesen der Datei", http.StatusInternalServerError)
log.Printf("Fehler beim Lesen der Datei: %v", err)
return
}
defer file.Close()
2024-03-08 14:59:31 +01:00
// Überprüfen Sie den MIME-Typ der Datei
buffer := make([]byte, 512) // Genug für die Erkennung des MIME-Typs
_, err = file.Read(buffer)
if err != nil {
http.Error(w, "Fehler beim Lesen der Datei", http.StatusInternalServerError)
log.Printf("Fehler beim Lesen der Datei für MIME-Typ-Erkennung: %v", err)
return
}
mimeType := http.DetectContentType(buffer)
if !strings.HasPrefix(mimeType, "image/") {
http.Error(w, "Nur Bild-Uploads sind erlaubt", http.StatusBadRequest)
log.Printf("Versuch, eine Nicht-Bild-Datei hochzuladen: %v", mimeType)
return
}
// Zurücksetzen des Dateizeigers, um die Datei vollständig zu kopieren
_, err = file.Seek(0, io.SeekStart)
if err != nil {
http.Error(w, "Fehler beim Zurücksetzen des Dateizeigers", http.StatusInternalServerError)
log.Printf("Fehler beim Zurücksetzen des Dateizeigers: %v", err)
return
}
2024-01-11 22:23:10 +01:00
// Hier können Sie den Dateinamen manipulieren oder einen anderen Speicherort wählen
uploadPath := "./uploads/" + handler.Filename
f, err := os.Create(uploadPath)
if err != nil {
http.Error(w, "Fehler beim Erstellen der Datei", http.StatusInternalServerError)
log.Printf("Fehler beim Erstellen der Datei: %v", err)
return
}
defer f.Close()
_, copyErr := io.Copy(f, file)
if copyErr != nil {
http.Error(w, "Fehler beim Kopieren der Datei", http.StatusInternalServerError)
log.Printf("Fehler beim Kopieren der Datei: %v", copyErr)
return
}
2024-01-11 22:38:55 +01:00
lastUploadTime = time.Now() // Setzen Sie die Zeit des letzten Uploads
2024-03-08 14:59:31 +01:00
// Nach erfolgreichem Upload:
2024-03-08 15:01:49 +01:00
tmpl, err := template.ParseFiles("templates/uploadSuccess.html")
if err != nil {
http.Error(w, "Fehler beim Laden des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Laden des Templates: %v", err)
return
}
data := struct {
Message string
Filename string
2024-03-08 14:59:31 +01:00
}{
2024-03-08 15:01:49 +01:00
Message: "Bild erfolgreich hochgeladen.",
Filename: handler.Filename,
}
2024-03-08 14:59:31 +01:00
2024-03-08 15:01:49 +01:00
err = tmpl.Execute(w, data)
if err != nil {
http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Rendern des Templates: %v", err)
return
}
2024-01-11 22:23:10 +01:00
} else {
2024-03-08 14:59:31 +01:00
2024-03-08 15:01:49 +01:00
tmpl, err := template.ParseFiles("templates/uploadForm.html")
if err != nil {
http.Error(w, "Fehler beim Laden des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Laden des Templates: %v", err)
return
}
err = tmpl.Execute(w, nil)
if err != nil {
http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Rendern des Templates: %v", err)
return
}
2024-01-11 22:23:10 +01:00
}
}
2024-03-08 15:32:44 +01:00
func imageHandler(w http.ResponseWriter, r *http.Request) {
2024-03-08 15:37:05 +01:00
// Extrahieren des Bildnamens aus dem URL-Pfad
imagePath := "./uploads/" + r.URL.Path[len("/image/"):]
// Stellen Sie sicher, dass das Bild existiert
if _, err := os.Stat(imagePath); os.IsNotExist(err) {
http.Error(w, "Bild nicht gefunden", http.StatusNotFound)
log.Printf("Bild nicht gefunden: %v", err)
return
}
// Setzen der korrekten MIME-Type basierend auf der Dateiendung
// Optional, verbessert aber die Kompatibilität
mimeType := "image/jpeg" // Standardwert; könnte dynamisch basierend auf der Dateiendung festgelegt werden
w.Header().Set("Content-Type", mimeType)
// Ausliefern des Bildes
http.ServeFile(w, r, imagePath)
2024-01-11 22:23:10 +01:00
}
2024-03-08 15:32:44 +01:00
func viewHandler(w http.ResponseWriter, r *http.Request) {
filePath := r.URL.Path[len("/view/"):]
imagePath := "./uploads/" + filePath
// Überprüfen, ob die Bilddatei existiert
if _, err := os.Stat(imagePath); os.IsNotExist(err) {
http.Error(w, "Bild nicht gefunden", http.StatusNotFound)
log.Printf("Bild nicht gefunden: %v", err)
return
}
// Verwenden von html/template zur sicheren Ausgabe von HTML
tmpl, err := template.ParseFiles("templates/viewImage.html")
if err != nil {
http.Error(w, "Fehler beim Laden des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Laden des Templates: %v", err)
return
}
data := struct {
Filename string
}{
Filename: filePath,
}
err = tmpl.Execute(w, data)
if err != nil {
http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Rendern des Templates: %v", err)
}
}