1、代码结构

2、运行实例


1、代码结构

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

  1.1)photoweb.go

 package main

 import (
"io"
"os"
"log"
"net/http"
"io/ioutil"
"html/template"
"path"
//"debug"
"fmt"
) const (
UPLOAD_DIR = "./uploads"
TEMPLATE_DIR = "./views"
ListDir = 0x0001
) var templates map[string] * template.Template = make(map[string] * template.Template) func init() {
fileInfoArr, err := ioutil.ReadDir(TEMPLATE_DIR)
check(err) var templateName, templatePath string
for _, fileInfo := range fileInfoArr {
templateName = fileInfo.Name()
if ext := path.Ext(templateName); ext != ".html" {
continue
}
templatePath = TEMPLATE_DIR + "/" + templateName;
t := template.Must(template.ParseFiles(templatePath))
rlname := realName(templateName)
log.Println("Loading template:", rlname)
templates[rlname] = t
}
} func realName(str string) string {
str = path.Base(str)
if str == "" {
return str
}
for i := ; i < len(str); i++ {
if '.' == str[i] {
return str[:i]
}
}
return str
} func uploadHandler(w http.ResponseWriter, r * http.Request) {
if r.Method == "GET" {
readerHtml(w, "upload", nil);
} if r.Method == "POST" {
f, h , err := r.FormFile("image")
if err != nil {
http.Error(w, err.Error(),
http.StatusInternalServerError)
return
}
filename := h.Filename
defer f.Close()
t, err := os.Create(UPLOAD_DIR + "/" + filename)
if err != nil {
http.Error(w, err.Error(),
http.StatusInternalServerError)
return
}
defer t.Close()
if _, err := io.Copy(t, f); err != nil {
http.Error(w, err.Error(),
http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/view?id="+filename,
http.StatusFound)
}
} func viewHandler(w http.ResponseWriter, r * http.Request) {
imageId := r.FormValue("id")
imagePath := UPLOAD_DIR + "/" + imageId
if exists := isExists(imagePath); !exists {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "image")
http.ServeFile(w, r, imagePath)
} func isExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
return os.IsExist(err)
} func listHandler(w http.ResponseWriter, r * http.Request) {
fileInfoArr, err := ioutil.ReadDir("./uploads")
if err != nil {
http.Error(w, err.Error(),
http.StatusInternalServerError)
fmt.Println("faild @ listHandler")
return
} locals := make(map[string]interface{})
images := []string{}
for _, fileInfo := range fileInfoArr {
if fileInfo.Name() != ".svn" {
images = append(images, fileInfo.Name())
}
}
locals["images"] = images readerHtml(w, "list", locals);
} func readerHtml(w http.ResponseWriter, tmpl string, locals map[string]interface{}){
err := templates[tmpl].Execute(w, locals)
check(err)
} func check(err error) {
if err != nil {
panic(err)
}
} func safeHandler(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r * http.Request) {
defer func() {
if e , ok := recover().(error); ok {
http.Error(w, e.Error(), http.StatusInternalServerError)
log.Println("WARN: panic in %v - %v", fn, e)
// log.Println(string(debug.Stack()))
}
}()
fn(w, r)
}
} func staticDirHandler(mux * http.ServeMux, prefix string, staticDir string, flags int) {
mux.HandleFunc(prefix, func(w http.ResponseWriter, r * http.Request) {
file := staticDir + r.URL.Path[len(prefix) - :]
if (flags & ListDir) == {
if exists := isExists(file); !exists {
http.NotFound(w, r)
fmt.Println(file, "not found")
return
}
}
fmt.Println("handle static dir")
http.ServeFile(w, r, file)
})
} func main() {
mux := http.NewServeMux()
staticDirHandler(mux, "/assets/", "./public", )
mux.HandleFunc("/", safeHandler(listHandler))
mux.HandleFunc("/view", safeHandler(viewHandler))
mux.HandleFunc("/upload", safeHandler(uploadHandler))
err := http.ListenAndServe(":8090", mux)
if err != nil {
log.Fatal("ListenAndServe: ", err.Error())
}
}

  1.2)views/list.html

 <!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>List</title>
</head>
<body>
<ol>
{{range $.images}}
<li><a href="/view?id={{.|urlquery}}">{{.|html}}</a></li>
{{end}}
</ol>
</body>
</html>

  1.3)views/upload.html

 <!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Upload</title>
</head>
<body>
<form method="POST" action="/upload" enctype="multipart/form-data">
Choose an image to upload: <input name="image" type="file" />
<input type="submit" value="Upload" />
</form>
</body>
</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)在浏览器端输入服务器地址

Go语言练习:网络编程实例——简易图片上传网站的更多相关文章

  1. Java网络编程(TCP协议-练习-上传文本文件)

    客户端: package WebProgramingDemo; import java.io.BufferedReader; public class UploadTextClient { /** * ...

  2. Thinkphp整合阿里云OSS图片上传实例

    Thinkphp3.2整合阿里云OSS图片上传实例,图片上传至OSS可减少服务器压力,节省宽带,安全又稳定,阿里云OSS对于做负载均衡非常方便,不用传到各个服务器了 首先引入阿里云OSS类库 < ...

  3. layui加tp5图片上传实例

    <div class="layui-fluid"> <div class="layui-row"> <form class=&qu ...

  4. Java学习之网络编程实例

    转自:http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html 多谢分享 网络编程 网络编程对于很多的初学者来说,都是很向往的一 ...

  5. php网络编程实例

    php网络编程实例 一.总结 一句话总结: socket_create():创建socket socket_bind():绑定IP和端口 socket_listen():监听客户端信息 <?ph ...

  6. java网络编程之图片上传

    输入输出流核心代码 所有的文件传输都是靠流,其中文件复制最具代表性.输入流和输出流,从输入流中读取数据写入到输出流中. InputStream in = 输入源; OutputStream os = ...

  7. PHP多图片上传实例demo

    upload.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...

  8. 网游中的网络编程3:在UDP上建立虚拟连接

    目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网络编程3:在UDP上建立虚拟连接 TODO 二.在UDP上建立虚拟连接 介绍 UDP是无连接的,一 ...

  9. asp.net 百度编辑器 UEditor 上传图片 图片上传配置 编辑器配置 网络连接错误,请检查配置后重试

    1.配置ueditor/editor_config.js文件,将 //图片上传配置区 ,imageUrl:URL+"net/imageUp.ashx" //图片上传提交地址 ,im ...

随机推荐

  1. Spring XML配置文件示例(一)——<Servlet name>-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  2. Oracle ASM

    一 Oracle ASM簡介 Oracle 10g推出的管理磁盤的新方式,用於取代LVM技術.主要用于RAC環境 二 Oracle ASM的配置安裝 1.安裝asm包 RedHat Linux5.x ...

  3. go sample - mongodb

    简单的mongodb 操作 package mainimport ( "fmt" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2 ...

  4. hdu 4784 Dinner Coming Soon(spfa + 优先队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4784 思路:建图,对于同一个universe来说,就按题目给的条件相连,对于相邻的universe,连 ...

  5. Struts2请求参数校验

    校验的分类 客户端数据校验 和 服务器端数据校验 客户端数据校验 ,通过JavaScript 完成校验 (改善用户体验,使用户减少出错 ) 服务器数据校验 ,通过Java代码 完成校验 struts2 ...

  6. JMeter中BeanShell用法总结(一)

    一.什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanS ...

  7. JDK BIO编程

    网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建 ...

  8. POJ 1159 回文串-LCS

    题目链接:http://poj.org/problem?id=1159 题意:给定一个长度为N的字符串.问你最少要添加多少个字符才能使它变成回文串. 思路:最少要添加的字符个数=原串长度-原串最长回文 ...

  9. json返回数据库的时间格式为/Date(1477294037000)/,怎样在前台进行格式化转换

    方法一: 原理是取中间的数,再转换成js的Date类型 function ChangeDateFormat(val) { if (val != null) { var date = new Date( ...

  10. Swift3.0语言教程字符串与文件的数据转换

    Swift3.0语言教程字符串与文件的数据转换 Swift3.0语言教程字符串与文件的数据转换,如果想要对字符串中的字符进行永久保存,可以将字符串中的字符写入到文件中.当然,开发者也可以将写入的内容进 ...