This is a creation in Article, where the information may have evolved or changed.
Package Mainimport ("FMT" "io" "net/http" "Log")//Get the size of an excuse type Sizer interface {size () int64}//Hello wor LD, the Web serverfunc helloserver (w http. Responsewriter, R *http. Request) {if "POST" = = R.method {file, _, Err: = R.formfile ("UserFile") if err! = Nil {http. Error (W, err. Error (), +) return} defer file. Close () F,err:=os. Create ("Filenametosaveas") defer f.close () io. Copy (F,file) fmt. fprintf (w, "Upload file Size:%d", file.) Sizer). Size ()) return}//upload page W.header (). ADD ("Content-type", "text/html") W.writeheader (HTML): = ' <form enctype= ' multipart/form-data ' action= '/hello ' method= "POST" > Send this file: <input name= "UserFile" type= "file"/> <input type= "Submit" value= "Send Fi" Le "/></form> ' io. WriteString (w, HTML)}func Main () {http. Handlefunc ("/hello", HelloServer) Err: = http. Listenandserve (": 12345", nil) if err! = Nil {log. Fatal ("Listenandserve:", Err)}} The client uploads the textCode: Func Upload () (err error) {//Create buffer buf: = new (bytes. Buffer)///caveat IMO dont use this for large files, \//Create a tmpfile and assemble your multipart from there (not Tested) W: = multipart. Newwriter (BUF)//Create file field fw, err: = W.createformfile ("File", "Helloworld.go")//file Here is important, must and server-side FORMFI Le consistent if err! = Nil {fmt. Println ("C") return err} FD, err: = OS. Open ("Helloworld.go") if err! = Nil {fmt. Println ("D") return err} defer FD. Close ()//Write file field from file to upload _, err = Io. Copy (FW, FD) if err! = Nil {fmt. Println ("E") return err}//Important If you don't close the multipart writer you won't have A//Termina Ting Boundry w.close () req, err: = http. Newrequest ("POST", "http://192.168.2.127/configure.go?portId=2", buf) if err! = Nil {fmt. Println ("F") return err} req. Header.set ("Content-type", W.formdatacontenttype ()) var client http. ClienT res, err: = client. Do (req) if err! = Nil {fmt. Println ("G") return err} io. Copy (OS. Stderr, Res. Body)//Replace this with Status.code check FMT. Println ("H") return err}
Handling file Uploads
You want to work with a user-uploaded file, for example, you're building a website like Instagram, and you need to store the photos taken by the user. How does this need to be achieved?
To enable a form to upload a file, the first step is to add the properties of the form enctype
, enctype
with the following three scenarios:
Application/x-www-form-urlencoded means all characters are encoded before sending (default)
Multipart/form-data characters are not encoded. You must use this value when you use a form that contains a file upload control.
The Text/plain space is converted to the "+" plus sign, but does not encode special characters.
Therefore, the HTML code for the form should look like this:
On the server side, we add a handlerfunc:
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) if err != nil { fmt.Println(err) return } defer f.Close() io.Copy(f, file) }}
As you can see from the code above, we need to call to process file uploads r.ParseMultipartForm
,
The parameters inside indicate maxMemory
that, ParseMultipartForm
after the call,
The uploaded file is stored in the maxMemory
size of the memory, if the file size exceeds maxMemory
, then the remainder will be stored in the system's temporary files.
We can r.FormFile
store the file by getting the file handle above and then using it in the instance io.Copy
.
You don't need to call when you get other non-file field information r.ParseForm
, because go automatically calls when needed. And once ParseMultipartForm
called once, the subsequent call will no longer be effective.
Through the above example we can see that we upload the file main three-step processing:
1. 表单中增加enctype="multipart/form-data"2. 服务端调用`r.ParseMultipartForm`,把上传的文件存储在内存和临时文件中3. 使用`r.FormFile`获取文件句柄,然后对文件进行存储等处理。
File handler is multipart. Fileheader, which stores the following structure information
type FileHeader struct {Filename stringHeader textproto.MIMEHeader// contains filtered or unexported fields}
We print out the above example code to upload the file information as follows
![](images/4.5.upload2.png?raw=true)
Server-side accepted information after printing a file upload
Client upload File
Our example above demonstrates how to upload a file from a form and then process the file on the server side,
In fact, go support the Simulation client form feature support file upload, detailed usage see the following example:
Package Mainimport ("bytes" "FMT" "io" "io/ioutil" "Mime/multipart" "Net/http" "OS") func postfile (filename string, TargetUrl string) Error {bodybuf: = &bytes. buffer{} bodywriter: = multipart. Newwriter (BODYBUF)//Critical one-step operation FileWriter, err: = Bodywriter.createformfile ("UploadFile", filename) if err! = Nil { Fmt. PRINTLN ("Error writing to buffer") return err}//Open file handle operation FH, err: = OS. Open (filename) if err! = Nil {fmt. PRINTLN ("Error opening file") Return err}//iocopy _, err = Io. Copy (FileWriter, FH) if err! = Nil {return err} ContentType: = Bodywriter.formdatacontenttype () bodyw Riter. Close () resp, err: = http. Post (TargetUrl, ContentType, 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}//sample Usagefunc main (){target_url: = "http://localhost:9090/upload" FileName: = "./astaxie.pdf" postfile (filename, Target_url)}
The example above shows a detailed example of how a client uploads a file to the server,
The client passes the multipart. Write writes the text stream of the file to a cache, and then calls the HTTP POST method to upload the cache to the server.
If you have other common fields such as username that need to be written at the same time, you can call multipart's Writefield method to write many other similar fields.