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,如需转载请自行联系原作者


相关文章
|
监控 算法 安全
基于 PHP 语言深度优先搜索算法的局域网网络监控软件研究
在当下数字化时代,局域网作为企业与机构内部信息交互的核心载体,其稳定性与安全性备受关注。局域网网络监控软件随之兴起,成为保障网络正常运转的关键工具。此类软件的高效运行依托于多种数据结构与算法,本文将聚焦深度优先搜索(DFS)算法,探究其在局域网网络监控软件中的应用,并借助 PHP 语言代码示例予以详细阐释。
305 1
|
11月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
521 61
|
10月前
|
监控 安全 Go
使用Go语言构建网络IP层安全防护
在Go语言中构建网络IP层安全防护是一项需求明确的任务,考虑到高性能、并发和跨平台的优势,Go是构建此类安全系统的合适选择。通过紧密遵循上述步骤并结合最佳实践,可以构建一个强大的网络防护系统,以保障数字环境的安全完整。
211 12
|
11月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
11月前
|
运维 网络协议 Go
Go网络编程:基于TCP的网络服务端与客户端
本文介绍了使用 Go 语言的 `net` 包开发 TCP 网络服务的基础与进阶内容。首先简述了 TCP 协议的基本概念和通信流程,接着详细讲解了服务端与客户端的开发步骤,并提供了简单回显服务的示例代码。同时,文章探讨了服务端并发处理连接的方法,以及粘包/拆包、异常检测、超时控制等进阶技巧。最后通过群聊服务端的实战案例巩固知识点,并总结了 TCP 在高可靠性场景中的优势及 Go 并发模型带来的便利性。
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
535 20
|
网络协议 算法 安全
Go语言的网络编程与TCP_UDP
Go语言由Google开发,旨在简单、高效和可扩展。本文深入探讨Go语言的网络编程,涵盖TCP/UDP的基本概念、核心算法(如滑动窗口、流量控制等)、最佳实践及应用场景。通过代码示例展示了TCP和UDP的实现,并讨论了其在HTTP、DNS等协议中的应用。最后,总结了Go语言网络编程的未来发展趋势与挑战,推荐了相关工具和资源。
446 5
|
存储 Go
【Go实战 | 电商平台】(7) 图片上传到七牛云
文章目录 1. 获取配置信息 2. config 3. upload 完整代码
597 0
【Go实战 | 电商平台】(7) 图片上传到七牛云
|
7月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
374 2
|
9月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
566 1

热门文章

最新文章