func HTMLEscape (w io.Writer, b [] byte) // 把 b 进行转义之后写到 w
func HTMLEscapeString (s string) string // 转义 s 之后返回结果字符串
func HTMLEscaper (args ...interface {}) string // 支持多个参数一起转义,返回结果字符串
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // 输出到服务器端
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // 输出到客户端
我们平常编写 Web 应用主要有两方面的数据验证,一个是在页面端的 js 验证 (目前在这方面有很多的插件库,比如 ValidationJS 插件),一个是在服务器端的验证。
确保从表单元素中得到一个值
if len(r.Form["username"][0])==0{
//值为空的处理
}
getint,err := strconv.Atoi(r.Form.Get("age"))
if err!=nil{
// 数字转化出错了,那么可能就不是数字
}
// 接下来就可以判断这个数字的大小范围了
if getint >100 {
// 太大了
}
//正则匹配:
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
return false
}
//手机号
if m, _ := regexp.MatchString(`^(1[3|4|5|8][0-9]\d{4,8})$`,r.Form.Get("mobile")); !m {
return false
}
//电子邮件
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,})\.([a-z]{2,4})$`, r.Form.Get("email")); !m {
fmt.Println("no")
}else{
fmt.Println("yes")
}
判断表单里的的值是否是预设的值
<select name="fruit">
<option value="apple">apple</option>
<option value="pear">pear</option>
<option value="banana">banana</option>
</select>
验证:
slice := []string{"apple","pear","banana"}
v:= r.Form.Get("fruit")
for _,item := range slice {
if item == v{
return true
}
}
return false
防止多次递交表单
解决方案:在表单中添加一个带有唯一值的隐藏字段。在验证表单时,检查该唯一值是否已经提交过,如果是就拒绝再次提交。
<input type="hidden" name="token" value="{{.}}">
r.ParseForm()
token := r.Form.Get("token")
if token != "" {
// 验证 token 的合法性
} else {
// 不存在 token 报错
}
处理文件上传
http.HandleFunc("/upload", upload)
// 处理 /upload 逻辑
func upload(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) // 获取请求的方法
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("upload.gtpl")
t.Execute(w, token)
} else {
r.ParseMultipartForm(32 << 20)
file, handler, err := r.FormFile("uploadfile")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Fprintf(w, "%v", handler.Header)
f, err := os.OpenFile("./test/"+handler.Filename,os.O_WRONLY|os.O_CREATE, 0666) // 此处假设当前目录下已存在test目录
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
io.Copy(f, file)
}
}
上传文件的三步处理:
1、表单中增加enctype="multipat/form-data"
2、服务端调用r.ParseMultipartForm,把上传的文件存储在内存和临时文件中
3、使用r.FormFile获取文件句柄
GO Web编程(四——表单)