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. fis3-postpackager-loader插件说明

    fis3-postpackager-loader 静态资源前端加载器,用来分析页面中使用的和依赖的资源(js或css), 并将这些资源做一定的优化后插入页面中.如把零散的文件合并. 注意 此插件做前端 ...

  2. (一)WebRTC手记之初探

    转自:http://www.cnblogs.com/fangkm/p/4364553.html WebRTC是HTML5支持的重要特性之一,有了它,不再需要借助音视频相关的客户端,直接通过浏览器的We ...

  3. 强化的单例属性_Effective Java

    Singleton指的是仅仅被实例化一次的类,比如唯一的系统组件等,成为Singleton的类测试起来也比较困难. 常用的方法: 1.公有静态final域+私有构造器 public class Egg ...

  4. 如果我可以重新学习iOS开发(转)

    在过去的几个月里,我一直在学习用Objective-C编写iOS app,最后我开始理清思绪.这比我想象中要难很多,也花了太长时间. 我经常遇到困难.感到沮丧,修复bug比实际写代码要花太多时间.但是 ...

  5. POJ 1840 Eqs 二分+map/hash

    Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 The co ...

  6. Vue入门笔记#过渡

    Vue过渡,可以在元素从DOM中移除,插入时自动调用过渡效果.根据设定,会适时的触发过渡效果. 在使用的目标标签里添加 transition: <div transition="my_ ...

  7. caffe中添加local层

    下载caffe-local,解压缩; 修改makefile.config:我是将cuudn注释掉,去掉cpu_only的注释; make all make test(其中local_test出错,将文 ...

  8. psql-02基本语法

    客户端 数据库: 创建:createdb mydb; 删除: dropdb mydb; 连接: 连接: psql mydb; 断开连接: \q 查看当前版本: select version(); 直接 ...

  9. js-变量、作用域和内存问题,引用类型

    变量.作用域和内存问题 1.变量可能包含两种不同数据类型的值:基本类型值以及引用类型值:引用类型值保存的是内存中的对象 2.对象是按值传递的, function setName(obj){ obj.n ...

  10. appium定位元素java篇【转】

    1.关于没有name,没有ID的元素的定位---通用篇解题思路:因为没有name,id:其实剩下的选择已不多,要么xpath,要么className.xpath木有好印象(稳定性不高,加之1.0x后需 ...