package main import ( "fmt" "io" "io/ioutil" "log" "net/http" "os" "reflect" ) const ( UPLOAD_DIR = "./uploads" ) func uploadHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { io.WriteString(w, "<html><form method=\"POST\" action=\"/upload\" "+ " enctype=\"multipart/form-data\">"+ "Choose an image to upload: <input name=\"image\" type=\"file\" />"+ "<input type=\"submit\" value=\"Upload\" />"+ "</form></html>") return } if r.Method == "POST" { f, h, err := r.FormFile("image") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } filename := h.Filename fmt.Println("filename:", filename) defer f.Close() //文件流句柄 t, err := os.Create(UPLOAD_DIR + "/" + filename) fmt.Println("filepath:", UPLOAD_DIR+"/"+filename) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer t.Close() //關閉臨時文件句柄 if _, err := io.Copy(t, f); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } http.Redirect(w, r, "/view?id="+filename, http.StatusFound) } } func viewHandler(w http.ResponseWriter, r *http.Request) { imageId := r.FormValue("id") imagePath := UPLOAD_DIR + "/" + imageId if exists := isExists(imagePath); !exists { http.NotFound(w, r) return } w.Header().Set("Content-Type", "image") //HTTP響應頭輸出格式 http.ServeFile(w, r, imagePath) } func isExists(path string) bool { _, err := os.Stat(path) if err == nil { return true } return os.IsExist(err) } func listHandler(w http.ResponseWriter, r *http.Request) { fileInfoArr, err := ioutil.ReadDir("./uploads") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } var listHtml string for _, fileInfo := range fileInfoArr { imgid := fileInfo.Name fmt.Println("type:", reflect.TypeOf(imgid)) listHtml += "<li><a href=\"/view?id=" + imgid() + "\">" + imgid() + "</a></li>" } io.WriteString(w, "<html><body><ol>"+listHtml+"</ol></body></html>") } func init() { //main函數以前執行 fmt.Println("init-----") } func safeHandler(fn http.HandlerFunc) http.HandlerFunc { //異常的處理 return func(w http.ResponseWriter, r *http.Request) { defer func() { if e, ok := recover().(error); ok { http.Error(w, err.Error(), http.StatusInternalServerError) log.Println("WARN: panic in %v - %v", fn, e) log.Println(string(debug.Stack())) } }() fn(w, r) } } //處理靜態資源 func staticDirHandler(mux *http.ServeMux, prefix string, staticDir string, flags int) { mux.HandleFunc(prefix, func(w http.ResponseWriter, r *http.Request) { file := staticDir + r.URL.Path[len(prefix)-1:] if (flags & ListDir) == 0 { if exists := isExists(file); !exists { http.NotFound(w, r) return } } http.ServeFile(w, r, file) }) } func main() { mux := http.NewServeMux() staticDirHandler(mux, "/assets/", "./public", 0) http.HandleFunc("/", safeHandler(listHandler)) http.HandleFunc("/view", safeHandler(viewHandler)) http.HandleFunc("/upload", safeHandler(uploadHandler)) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("ListenAndServe: ", err.Error()) } }