Go语言练习:网络编程实例——简易图片上传网站

1、代码结构

2、运行实例


 

1、代码结构

$ tree
.
├── photoweb.go
├── public
│   ├── css
│   ├── images
│   └── js
├── uploads
└── views
    ├── list.html
    └── upload.html

  1.1)photoweb.go

  1 package main
  2 
  3 import (
  4     "io"
  5     "os"
  6     "log"
  7     "net/http"
  8     "io/ioutil"
  9     "html/template"
 10     "path"
 11     //"debug"
 12     "fmt"
 13 )
 14 
 15 const (
 16     UPLOAD_DIR = "./uploads"
 17     TEMPLATE_DIR = "./views"
 18     ListDir = 0x0001
 19 )
 20 
 21 var templates map[string] * template.Template = make(map[string] * template.Template)
 22 
 23 func init() {
 24     fileInfoArr, err := ioutil.ReadDir(TEMPLATE_DIR)
 25     check(err)
 26 
 27     var templateName, templatePath string
 28     for _, fileInfo := range fileInfoArr {
 29         templateName = fileInfo.Name()
 30         if ext := path.Ext(templateName); ext != ".html" {
 31             continue
 32         }
 33         templatePath = TEMPLATE_DIR + "/" + templateName;
 34         t := template.Must(template.ParseFiles(templatePath))
 35         rlname := realName(templateName)
 36         log.Println("Loading template:", rlname)
 37         templates[rlname] = t
 38     }
 39 }
 40 
 41 func realName(str string) string {
 42     str = path.Base(str)
 43     if str == "" {
 44         return str
 45     }
 46     for i := 0; i < len(str); i++ {
 47         if '.' == str[i] {
 48             return str[:i]
 49         }
 50     }
 51     return str
 52 }
 53 
 54 func uploadHandler(w http.ResponseWriter, r * http.Request) {
 55     if r.Method == "GET" {
 56         readerHtml(w, "upload", nil);
 57     }
 58 
 59     if r.Method == "POST" {
 60         f, h , err := r.FormFile("image")
 61         if err != nil {
 62             http.Error(w, err.Error(),
 63             http.StatusInternalServerError)
 64             return
 65         }
 66         filename := h.Filename
 67         defer f.Close()
 68         t, err := os.Create(UPLOAD_DIR + "/" + filename)
 69         if err != nil {
 70             http.Error(w, err.Error(),
 71             http.StatusInternalServerError)
 72             return
 73         }
 74         defer t.Close()
 75         if _, err := io.Copy(t, f); err != nil {
 76             http.Error(w, err.Error(),
 77             http.StatusInternalServerError)
 78             return
 79         }
 80         http.Redirect(w, r, "/view?id="+filename,
 81         http.StatusFound)
 82     }
 83 }
 84 
 85 func viewHandler(w http.ResponseWriter, r * http.Request) {
 86     imageId        := r.FormValue("id")
 87     imagePath    := UPLOAD_DIR + "/" + imageId
 88     if exists := isExists(imagePath); !exists {
 89         http.NotFound(w, r)
 90         return
 91     }
 92     w.Header().Set("Content-Type", "image")
 93     http.ServeFile(w, r, imagePath)
 94 }
 95 
 96 func isExists(path string) bool {
 97     _, err := os.Stat(path)
 98     if err == nil {
 99         return true
100     }
101     return os.IsExist(err)
102 }
103 
104 func listHandler(w http.ResponseWriter, r * http.Request) {
105     fileInfoArr, err := ioutil.ReadDir("./uploads")
106     if err != nil {
107         http.Error(w, err.Error(),
108         http.StatusInternalServerError)
109         fmt.Println("faild @ listHandler")
110         return
111     }
112 
113     locals := make(map[string]interface{})
114     images := []string{}
115     for _, fileInfo := range fileInfoArr {
116         if fileInfo.Name() != ".svn" {
117             images = append(images, fileInfo.Name())
118         }
119     }
120     locals["images"] = images
121 
122     readerHtml(w, "list", locals);
123 }
124 
125 func readerHtml(w http.ResponseWriter, tmpl string, locals map[string]interface{}){
126     err := templates[tmpl].Execute(w, locals)
127     check(err)
128 }
129 
130 func check(err error) {
131     if err != nil {
132         panic(err)
133     }
134 }
135 
136 func safeHandler(fn http.HandlerFunc) http.HandlerFunc {
137     return func(w http.ResponseWriter, r * http.Request) {
138         defer func() {
139             if e , ok := recover().(error); ok {
140                 http.Error(w, e.Error(), http.StatusInternalServerError)
141                 log.Println("WARN: panic in %v - %v", fn, e)
142 //                log.Println(string(debug.Stack()))
143             }
144         }()
145         fn(w, r)
146     }
147 }
148 
149 func staticDirHandler(mux * http.ServeMux, prefix string, staticDir string, flags int) {
150     mux.HandleFunc(prefix, func(w http.ResponseWriter, r * http.Request) {
151         file := staticDir + r.URL.Path[len(prefix) - 1:]
152         if (flags & ListDir) == 0 {
153             if exists := isExists(file); !exists {
154                 http.NotFound(w, r)
155                 fmt.Println(file, "not found")
156                 return
157             }
158         }
159         fmt.Println("handle static dir")
160         http.ServeFile(w, r, file)
161     })
162 }
163 
164 func main() {
165     mux := http.NewServeMux()
166     staticDirHandler(mux, "/assets/", "./public", 0)
167     mux.HandleFunc("/", safeHandler(listHandler))
168     mux.HandleFunc("/view", safeHandler(viewHandler))
169     mux.HandleFunc("/upload", safeHandler(uploadHandler))
170     err := http.ListenAndServe(":8090", mux)
171     if err != nil {
172         log.Fatal("ListenAndServe: ", err.Error())
173     }
174 }
View Code

  1.2)views/list.html

 1 <!doctype html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title>List</title>
 6     </head>
 7     <body>
 8         <ol>
 9             {{range $.images}}
10             <li><a href="/view?id={{.|urlquery}}">{{.|html}}</a></li>
11             {{end}}
12         </ol>
13     </body>
14 </html>
View Code

  1.3)views/upload.html

 1 <!doctype html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title>Upload</title>
 6     </head>
 7     <body>
 8         <form method="POST" action="/upload" enctype="multipart/form-data">
 9             Choose an image to upload: <input name="image" type="file" />
10             <input type="submit" value="Upload" />
11         </form>
12     </body>
13 </html>
View Code

2、运行及结果

  2.1)运行

$ go run photoweb.go 
2015/07/25 02:15:24 Loading template: list
2015/07/25 02:15:24 Loading template: upload

  2.2)在浏览器端输入服务器地址

 

posted @ 2015-07-25 02:20  fengbohello  阅读(928)  评论(0编辑  收藏  举报