0.首先肯定是用http 的post
Content-Type | value | body字符处理 | 用途 |
---|---|---|---|
application/x-www-from-urlencoded | key1=value1&key2=value2 | 空格转换为 “+”+url编码 | 一般的post多是用这个 |
binary/octet-stream | 二进制 | 直接传送二进制 | 传单个文件 |
multipart/form-data | 具体见下图 | 会有分隔符+二进制 | 传多个文件 |
text/plain ?raw ? | 任意文本 | 空格转换为 “+” | json数据 |
似乎比较通用的上传文件的方式是用xhr(XMLHttpRequest) 3
下面把我搜到的都列一下。
1.binary/octet-stream
https://my.oschina.net/zhizhisoft/blog/1815323
2.multipart/form-data
精简版代码(包括前端和后端):
https://stackoverflow.com/questions/19267336/golang-http-handle-big-file-upload
javascript
主要用:XMLHttpRequest+form-data
js: https://www.cnblogs.com/007sx/p/7520529.html
另一个版本:4
var files = document.getElementById('pic').files; //files是文件选择框选择的文件对象数组
if(files.length == 0) return;
var form = new FormData(),
url = 'http://.......', //服务器上传地址
file = files[0];
form.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open("post", url, true);
//上传进度事件
xhr.upload.addEventListener("progress", function(result) {
if (result.lengthComputable) {
//上传进度
var percent = (result.loaded / result.total * 100).toFixed(2);
}
}, false);
xhr.addEventListener("readystatechange", function() {
var result = xhr;
if (result.status != 200) { //error
console.log('上传失败', result.status, result.statusText, result.response);
}
else if (result.readyState == 4) { //finished
console.log('上传成功', result);
}
});
xhr.send(form); //开始上传
go
go(buffer io.copy):5
func ReceiveFile(w http.ResponseWriter, r *http.Request) {
var Buf bytes.Buffer
// in your case file would be fileupload
file, header, err := r.FormFile("file")
if err != nil {
panic(err)
}
defer file.Close()
name := strings.Split(header.Filename, ".")
fmt.Printf("File name %s\n", name[0])
// Copy the file data to my buffer
io.Copy(&Buf, file)
// do something with the contents...
// I normally have a struct defined and unmarshal into a struct, but this will
// work as an example
contents := Buf.String()
fmt.Println(contents)
// I reset the buffer in case I want to use it again
// reduces memory allocations in more intense projects
Buf.Reset()
// do something else
// etc write header
return
}
另外一个版本(file & iocopy & ParseMultipartForm):6 7
http.HandleFunc("/upload", upload)
// upload logic
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)
}
}
注意:r.ParseMultipartForm(32 << 20)
,似乎是设置读文件的缓冲区的大小为1M?超过的话写入临时文件?
一个alternative 是用 r.MultipartReader()
8传说是会以stream 方式处理:9
_, err := r.MultipartReader()
if err != nil {
println(err)
return
}
multiPart.Reader的使用 10
(也可以参考官方的单元测试11)
func handle(w http.ResponseWriter, req *http.Request) {
partReader := multipart.NewReader(req.Body, boundary)
buf := make([]byte, 256)
for {
part, err := partReader.NextPart()
if err == io.EOF {
break
}
var n int
for {
n, err = part.Read(buf)
if err == io.EOF {
break
}
fmt.Printf(string(buf[:n]))
}
fmt.Printf(string(buf[:n]))
}
}
js md5 计算
https://blog.csdn.net/u012743824/article/details/78927917
js 支持拖拽
https://blog.csdn.net/u012743824/article/details/79021670
Range的
在搜索相关内容时,可能会发现http range这个,这个是用来做下载文件的断断续传的。
https://www.cnblogs.com/findumars/p/5745345.html
- https://blog.csdn.net/qq_33706382/article/details/78168325 ↩
- https://www.w3schools.com/tags/att_form_enctype.asp ↩
- https://stackoverflow.com/questions/29659154/what-is-the-best-way-to-upload-files-in-a-modern-browser ↩
- https://blog.csdn.net/lovelyelfpop/article/details/71421123 ↩
- https://stackoverflow.com/questions/40684307/how-can-i-receive-an-uploaded-file-using-a-golang-net-http-server ↩
- https://astaxie.gitbooks.io/build-web-application-with-golang/en/04.5.html ↩
- https://studygolang.com/articles/2472 ↩
- https://yanyiwu.com/work/2015/01/07/golang-http-formvalue.html ↩
- https://stackoverflow.com/questions/48352584/efficiently-handling-http-uploads-of-many-large-files-in-go ↩
- https://gist.github.com/ZenGround0/49e4a1aa126736f966a1dfdcb84abdae ↩
- https://golang.org/src/mime/multipart/example_test.go ↩