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> `
2023/8/4
go-lang small http file server with upload function
ChatGPT 寫的,還沒看能不能動...
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言