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. sqlplus 中spool命令的简单用法

    spool基本格式: spool 路径+文件名 select col1||','||col2||','||col3||','||col4||'..' from tablename; spool off ...

  2. HP SAN Switch光纖交換機命令行畫zone

    有時候我們無法登陸網頁交互界面去操縱交換機,如下提供了命令行方式從交換機劃zone 1.創建別名 alicreate "SummaryDB_N", "211,14; 21 ...

  3. AgileEAS.NET SOA 中间件2013第四季度发布&部分功能开源预告

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  4. linux中的基础正则表达式

    基础的正则表达式如下 RE字符 意义与范例 ^word 待查找的字符串(word)在行首 word$ 待查找的字符串(word)在行尾 . 代表一定有一个任意字符的字符 \ 转义字符,将特殊字符的特殊 ...

  5. GitHub 使用教程图文详解(转)

    大纲: 一.前言 二.GitHub简介 三.注册GitHub账号 四.配置GitHub 五.使用GitHub 六.参与GitHub中其它开源项目 七.总结 注,GitHub官网:https://git ...

  6. java的分层开发

    既然是分层开发,首先我们需要知道的是分为那几个层,并且是干什么的? 1.实体层(entity) 对应数据库中的一张表,有了它可以降低耦合性,同时也是数据的载体. 2.数据访问对象(data acces ...

  7. sql篇 select from where group by having order by

    以前,自己总是记不住如何用group by,如何用order by,什么时候用group by,什么时候用order by,什么时候两者一起用,怎么用,谁先谁后,现在,我们就一起来说一下Select ...

  8. 二维数组&多维数组

    1.二维数组 二维数组由多个一维数组组成,其定义方式: ,]{ {,,,}, {,,,}, {,,,} }; 二维数组中括号中,逗号左边表示一维数组的个数,也可以说控制行,逗号后面的数表示每个一维数组 ...

  9. 第一个vs2013控制台程序

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. WinForm使用WebBrowser操作HTML页面的Element

    前言 在 Window Form 应用程序如果需要浏览网页时可以崁入 WebBrowser 控件,但如果需要操作崁入的 HTML 的网页元素,就需要额外的操作,以下纪录几种操作 HTML 元素的方法以 ...