分享
  1. 首页
  2. 文章

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

fengbohello · · 3655 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:fengbohello

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

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3655 次点击 ∙ 3 赞
3 回复 | 直到 2025年05月09日 13:38:04
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏