2023/8/4

go-lang small http file server with upload function

ChatGPT 寫的,還沒看能不能動...
package main

import (
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

func main() {
	http.HandleFunc("/", handleFileServer)
	http.HandleFunc("/upload", handleUpload)

	// Start the server on port 8080
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic(err)
	}
}

func handleFileServer(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	dirPath := "." // Current directory
	filePath := filepath.Join(dirPath, r.URL.Path)
	file, err := os.Open(filePath)
	if err != nil {
		http.Error(w, "File not found", http.StatusNotFound)
		return
	}
	defer file.Close()

	// Check if the path is a directory
	fileInfo, err := file.Stat()
	if err != nil {
		http.Error(w, "Failed to get file info", http.StatusInternalServerError)
		return
	}
	if fileInfo.IsDir() {
		renderDirectory(w, filePath)
		return
	}

	// Serve the file if it's not a directory
	http.ServeFile(w, r, filePath)
}

func renderDirectory(w http.ResponseWriter, dirPath string) {
	tmpl, err := template.New("directory").Parse(directoryTemplate)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// Read the directory content
	dir, err := os.ReadDir(dirPath)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	data := struct {
		DirectoryName string
		Files         []string
	}{
		DirectoryName: dirPath,
		Files:         make([]string, 0),
	}

	for _, entry := range dir {
		data.Files = append(data.Files, entry.Name())
	}

	// Render the template
	err = tmpl.Execute(w, data)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
	}
}

func handleUpload(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// Limit the maximum file size to 10 MB
	r.ParseMultipartForm(10 << 20)

	// Get the uploaded file
	file, handler, err := r.FormFile("file")
	if err != nil {
		http.Error(w, "Failed to get file from request", http.StatusBadRequest)
		return
	}
	defer file.Close()

	// Create the file in the current directory
	f, err := os.Create(handler.Filename)
	if err != nil {
		http.Error(w, "Failed to create file on server", http.StatusInternalServerError)
		return
	}
	defer f.Close()

	// Copy the uploaded file to the server
	_, err = io.Copy(f, file)
	if err != nil {
		http.Error(w, "Failed to save file on server", http.StatusInternalServerError)
		return
	}

	// Redirect back to the directory listing
	http.Redirect(w, r, "/", http.StatusFound)
}

const directoryTemplate = `
<!DOCTYPE html>
<html>
<head>
	<title>Directory Listing: {{ .DirectoryName }}</title>
</head>
<body>
	<h1>Directory Listing: {{ .DirectoryName }}</h1>
	<ul>
		{{ range .Files }}
		<li><a href="{{ . }}">{{ . }}</a></li>
		{{ end }}
	</ul>
	<form action="/upload" method="post" enctype="multipart/form-data">
		<input type="file" name="file">
		<input type="submit" value="Upload">
	</form>
</body>
</html>
`

沒有留言:

張貼留言