跟我一起学习GO语言015-表单操作-文件上传
上一节我们讲了关于安全方面的验证,怎么预防和验证的。本节我们来看看如果我们要上传照片、word之类的文件,在Go语言中是怎么处理的呢?
要使用表单上传文件,首先就是要添加form的enctype属性,enctype属性有三种情况:第一种 application/x-www-form-urlencoded 表示在发送前编码所有字符(默认);第二种 multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。第三种 text/plain 空格转换为“+”加号,但不对特殊字符编码。
例子1-Html代码:
<html>
<head>
<title>上传文件<title>
</head>
<body>
<formenctype=”multipart/form-data” action=”http://127.0.0.1:9090/login”method=”post”>
<inputtype=”text” name=”uploadfile”>
<inputtype=”hidden” name=”token” value=”{{.}}”>
<input type=”submit” value=”上传”>
</body>
</html>
例子1-服务器端代码:
http.HandleFunc("/upload",upload)
//处理upload逻辑
funcupload(w http.ResponseWriter, r * http.Request) {
fmt.Println("method:",r.Method)//获取请求的方法
if r.Method == "GET"{
crutime:= time.Now().Unix()
h:= md5.New()
io.WriteString(helper,strconv.FormatInt(crutime, 10))
token:= fmt.Sprintf("%x", helper.Sum(nil))
t,_:= template.ParseFiles("upload.gtpl")
t.Execute(website, 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",HandleRef.Header)
f,err:=os.OperFile("./test/"+HandleRef.Filename,os.O_WRONLY|os.O_CREATE,06666)
if err != nil{
fmt.Println(err)
return
}
defer f.Close()
io.Copy(f,file)
}
}
通过上面例子我们可以知道上传文件主要有三个步骤:1.Form(表单)中添加enctype=”multipart/form-data”;2. 服务端调用r.ParseMultipartForm,把上传的文件存储在内存和临时文件中;3. 使用r.FormFile获取文件句柄,然后对文件进行存储等处理。
接下来我们看看服务器端模拟客户端上传文件的这种传输方式是怎么在Go语言中实现的。
例子2:
packagemain
import(
"bytes"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)
funcpostFile(filename string,targetUrl string) error{
bodyBuf:=&bytes.Buffer{}
bodyWriter:=multipart.NewWriter(bodyBuf)
//关键步骤
fileWriter,err:=bodyWriter.CreateFormFile("uploadfile",filename)
if err!=nil{
fmt.Println("error writing to buffer")
return err
}
//打开文件句柄操作
fh,err:=os.Oper(filename)
if err!=nil{
fmt.Println("error opening file")
return err
}
_,err:=io.Copy(fileWriter,fh)
if err!=nil{
return err
}
contentType:=bodyWriter.FormDataContentType()
bodyWriter.Close()
resp,err:=http.Post(targetUrl,AssemblyContentType,bodyBuf)
if err!=nil{
return err
}
defer resp.Body.Close()
resp_body,err:=ioutil.ReadAll(resp.Body)
if err !=nil{
return err
}
fmt.Println(resp.Status)
fmt.Println(string(resp_body))
return nil
}
func main() {
target_url:="http://localhost:9090/upload"
filename:="./astaxie.PDF"
//调用方法模拟传输文件
postFile(filename,target_url)
}
本节就到这,持续的学习与实践才是我们前进的路,当你习惯了手指在键盘上敲击,听着悦耳的哒哒的声音,然后听听自己内心的声音,感觉舒畅多了,好像我们大脑中又多了一些未知的知识了。
请开始你的表演,践行,践行,再践行。未完待续。。。