Golang HTTP上传下载
代码
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"regexp"
)
func main() {
reFilename := regexp.MustCompile(`[^/]+`)
uploadRoot, _ := filepath.Abs(".")
downloadRoot, _ := filepath.Abs(".")
http.HandleFunc("/upload/", func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(10 * 1024 * 1024)
if err != nil {
log.Printf("ParseMultipartFrom error: %s\n", err)
return
}
for _, headers := range r.MultipartForm.File {
for _, header := range headers {
log.Printf("Begin upload file: %s\n", header.Filename)
if !reFilename.MatchString(header.Filename) {
log.Printf("Accept filename %s error: cannot cotains /\n", header.Filename)
return
}
filePath := filepath.Join(uploadRoot, header.Filename)
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Printf("Create file %s error: %s\n", filePath, err)
return
}
srcFile, err := header.Open()
if err != nil {
log.Printf("open header failed: %s\n", err)
}
_, err = io.Copy(dstFile, srcFile)
if err != nil {
fmt.Printf("Write file %s error: %s\n", filePath, err)
}
_, _ = srcFile.Close(), dstFile.Close()
}
}
})
http.Handle("/download/", http.StripPrefix(
"/download/",
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Begin download file: %s\n", r.URL.String())
http.FileServer(http.Dir(downloadRoot)).ServeHTTP(w, r)
}),
))
log.Println("http server start at :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalln(err)
}
}
验证
HTTP上传原理
# 同时上传两个文件upload.txt 和 upload.7z
curl -v -F upload.txt=@"upload.txt" -F upload.7z=@"upload.7z" http://127.0.0.1:8080/upload/
Fiddler 抓包内容如下
参考: https://blog.csdn.net/qq_33706382/article/details/78168325
POST http://127.0.0.1:8080/upload/ HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: curl/7.58.0
Accept: */*
Connection: Keep-Alive
Content-Length: 676
Content-Type: multipart/form-data; boundary=------------------------b3729e791dc27dbc
--------------------------b3729e791dc27dbc
Content-Disposition: form-data; name="upload.txt"; filename="upload.txt"
Content-Type: text/plain
upload.txt content
--------------------------b3729e791dc27dbc
Content-Disposition: form-data; name="upload.7z"; filename="upload.7z"
Content-Type: application/octet-stream
7z'ybo]: E#n@ѺwZnũ:DbZ_9DH
="%? N0Ĩ(^eGGKɲ(mC6ç!W3xQQ
^]
nD'[') fGjx E1;fm
G|Aw
!!
e?
UPLOAD.TXT
dŠ
--------------------------b3729e791dc27dbc--