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)在浏览器端输入服务器地址

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

 

你可能感兴趣的:(网络编程)