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

简介:

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 }
复制代码

  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>
复制代码

  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>
复制代码

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

 



本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/4675161.html,如需转载请自行联系原作者


相关文章
|
7天前
|
数据采集 监控 安全
公司网络监控软件:Zig 语言底层优化保障系统高性能运行
在数字化时代,Zig 语言凭借出色的底层控制能力和高性能特性,为公司网络监控软件的优化提供了有力支持。从数据采集、连接管理到数据分析,Zig 语言确保系统高效稳定运行,精准处理海量网络数据,保障企业信息安全与业务连续性。
27 4
|
1月前
|
弹性计算 监控 数据库
制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程
本文通过一个制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程,展示了企业级应用上云的实践方法与显著优势,包括弹性计算资源、高可靠性、数据安全及降低维护成本等,为企业数字化转型提供参考。
55 5
|
1月前
|
安全 网络协议 网络安全
企业网站建设时如何保障网站网络安全
企业网站建设时如何保障网站网络安全?
59 15
|
1月前
|
数据库连接 Go 数据库
Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性
本文探讨了Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性;防御编程则强调在编码时考虑各种错误情况,确保程序健壮性。文章详细介绍了这两种技术在Go语言中的实现方法及其重要性,旨在提升软件质量和可靠性。
34 1
|
13天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数
|
1月前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
62 13
|
1月前
|
网络协议 安全 Go
Go语言的网络编程基础
【10月更文挑战第28天】Go语言的网络编程基础
48 8
|
5月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
|
5月前
|
Java API 网络安全
Java网络编程入门
Java网络编程入门
|
5月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解