提前说明一下:代码参考了《Go语言编程》,稍有变动, 自己亲自玩了一遍。

 

       之前玩过go web server, 现在来用go来搭建一个简单的图片上传网站, 工作目录是:~/photoweb , 而~/photoweb/uploads用来存图片,代码photoweb.go在~/photoweb目录下。

       看服务器代码, ~/photoweb/photoweb.go的内容为:

package main
 
import (
	"io"
	"os"
	"log"
	"net/http"
)

const (
	UPLOAD_DIR = "./uploads"
)

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
    	str := `
			<html>
			<head>
			<meta charset="utf-8">
			<title>Upload</title>
			</head>
			<body>
			<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>
			</body>
			</html>`
    
    	io.WriteString(w, str)
	}

	// 处理图片上传
	if r.Method == "POST" {
		f, h, err := r.FormFile("image")
		if err != nil {
			http.Error(w, err.Error(),
				http.StatusInternalServerError)
			return
		}
		filename := h.Filename
		defer f.Close()

		t, err := os.Create(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
		}
	}

}

func main() {
	http.HandleFunc("/upload", uploadHandler)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}
}

       在浏览器中执行:http://127.0.0.1:8080/upload

       后台代码进入GET分支, 给浏览器端返回一段html代码,展示成html元素, 供用户上传图片, 选择图片, 点击Upload按钮上传后, 后台代码进入POST分支, 于是把图片存到了~/photoweb/uploads中。实际check了一下, 该目录下果然有此图片。

 

       为了便于在浏览器上直接查看上传的图片, 可以修改下服务器代码, 增加Redirect, 如下:

package main
 
import (
	"io"
	"os"
	"log"
	"net/http"
)

const (
	UPLOAD_DIR = "./uploads"
)

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
    	str := `
			<html>
			<head>
			<meta charset="utf-8">
			<title>Upload</title>
			</head>
			<body>
			<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>
			</body>
			</html>`
    
    	io.WriteString(w, str)
	}

	// 处理图片上传
	if r.Method == "POST" {
		f, h, err := r.FormFile("image")
		if err != nil {
			http.Error(w, err.Error(),
				http.StatusInternalServerError)
			return
		}
		filename := h.Filename
		defer f.Close()

		t, err := os.Create(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 isExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}

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.ServeFile(w, r, imagePath)
}

func main() {
	http.HandleFunc("/view", viewHandler)
	http.HandleFunc("/upload", uploadHandler)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}
}

       重启服务,重新访问http://127.0.0.1:8080/upload, 然后选择图片, 点击Upload上传, 结果在服务器对应的目录中有该图片, 且在浏览器中显示了该图片。

       如上代码很简单, 我之前在Apatch下写过类似的图片上传服务器, 道理基本相同。

 

       好了, 不多说。

        

 


本文转载:CSDN博客