go 语言 搭建 图片上传 服务器

工具: LiteIDE

配置:

 

代码: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>

 

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>

 

photoweb.go: 

// photoweb
package main

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"runtime/debug"
	"strings"
)

const (
	ListDir      = 0x0001
	TEMPLATE_DIR = "./view"
	UPLOAD_DIR   = "./uploads"
)

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()
		var ext string
		if ext = path.Ext(templateName); ext != ".html" {
			continue
		}
		templatePath = TEMPLATE_DIR + "/" + templateName
		log.Println("Loading template:", templatePath)
		t := template.Must(template.ParseFiles(templatePath))
		tmpl := strings.TrimSuffix(templateName, ext)
		templates[tmpl] = t
	}
}

func safeHandler(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err, ok := recover().(error); ok {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				// 或者输出自定义的 50x 错误页面
				// w.WriteHeader(http.StatusInternalServerError)
				// renderHtml(w, "error", e)
				// logging
				log.Println("WARN: panic in %v - %v", fn, err)
				log.Println(string(debug.Stack()))
			}
		}()
		fn(w, r)
	}
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}
func renderHtml(w http.ResponseWriter, tmpl string, locals map[string]interface{}) {
	err := templates[tmpl].Execute(w, locals)
	check(err)
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		//io.WriteString(w, "<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>")
		//		t, err := template.ParseFiles("upload.html")
		//		if err != nil {
		//			http.Error(w, err.Error(), http.StatusInternalServerError)
		//			return
		//		}
		//		t.Execute(w, nil)
		//		return
		renderHtml(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
	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)
	//		return
	//	}
	//	locals := make(map[string]interface{})
	//	images := []string{}
	//	for _, fileInfo := range fileInfoArr {
	//		images = append(images, fileInfo.Name())
	//	}
	//	locals["images"] = images
	//	t, err := template.ParseFiles("list.html")
	//	if err != nil {
	//		http.Error(w, err.Error(),
	//			http.StatusInternalServerError)
	//		return
	//	}
	//	t.Execute(w, locals)

	fileInfoArr, err := ioutil.ReadDir("./uploads")
	check(err)
	locals := make(map[string]interface{})
	images := []string{}
	for _, fileInfo := range fileInfoArr {
		images = append(images, fileInfo.Name())
	}
	locals["images"] = images
	renderHtml(w, "list", locals)

}

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)-1:]
		if (flags & ListDir) == 0 {
			if exists := isExists(file); !exists {
				http.NotFound(w, r)
				return
			}
		}
		http.ServeFile(w, r, file)
	})
}

func main() {
	fmt.Println("Hello World!")
	mux := http.NewServeMux()
	staticDirHandler(mux, "/assets/", "./public", 0)
	mux.HandleFunc("/", safeHandler(listHandler))
	mux.HandleFunc("/view", safeHandler(viewHandler))
	mux.HandleFunc("/upload", safeHandler(uploadHandler))
	err := http.ListenAndServe(":8080", mux)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}

}

  

 测试:

 

 

 

 参考:《GO 语言编程》

 

转载于:https://www.cnblogs.com/20170722-kong/p/10871768.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
搭建个人博客是非常合适的应用场景之一,而Go语言作为一门简洁高效的编程语言,也可以用来实现这个目标。下面是一些关于使用Go语言搭建个人博客的优势和步骤。 首先,让我们看一下使用Go语言搭建个人博客的优势: 1. 高效稳定:Go语言具有高并发性能和出色的部署特性,可以确保你的个人博客在高流量情况下依然稳定运行。 2. 直接生成静态文件:使用Go语言编写博客程序时,可以直接生成静态文件,无需依赖数据库或其他复杂的系统组件。 3. 跨平台性:Go语言可以在多个操作系统上运行,不仅可以在Linux服务器上使用,还可以在Windows或Mac机器上进行开发。 下面是使用Go语言搭建个人博客的步骤: 1. 确定功能需求:在开始搭建个人博客之前,需要明确自己的功能需求,例如文章列表、分类、标签、评论等。根据需求确定后台和前台的功能。 2. 设计数据库结构:根据需求设计数据库结构,用于存储博客文章、分类、标签、用户等信息。 3. 开发后台接口:通过使用Go语言的Web框架,可以开发后台接口,实现博客文章的增删改查,用户登录注册等功能。 4. 设计前端页面:使用HTML和CSS等技术设计前端页面,展示博客文章、分类、标签等信息。 5. 前后端数据交互:通过Ajax等技术实现前后端数据交互,例如前端通过接口获取博客文章列表,后台接收到前端请求后,查询数据库并返回对应的结果。 6. 部署与发布:将开发好的博客程序部署到服务器上,并配置好域名和网络环境,确保博客可以正常访问。 总结起来,使用Go语言搭建个人博客可以提供高效稳定的性能,通过合理的功能设计和数据库结构,加上前后端的配合,可以实现一个完善的个人博客系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值