文件已经上传到服务器翻译,服务器接受上传的优化 翻译+源码分析
一般的做法
err := r.ParseMultipartForm(32 << 20) // 32Mb
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
问题
请注意,32Mb是分配给请求体的字节存储在内存中,而不是请求体的限制,当满(33Mb)时,它将写入临时目录。
查看源码
src/net/http/request.go中
func (r *Request) ParseMultipartForm(maxMemory int64) error {
...
f, err := mr.ReadForm(maxMemory)
...
}
func (r *Reader) ReadForm(maxMemory int64) (*Form, error) {
return r.readForm(maxMemory)
}
func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
...
n, err := io.CopyN(&b, p, maxMemory+1)
...
if n > maxMemory {
可以看到这里把剩余的内容写入到临时文件了
file, err := ioutil.TempFile("", "multipart-")
size, err := io.Copy(file, io.MultiReader(&b, p))
...
}
...
}
解决方案一
直接限制客户端上传大小,但是有时候这个数字不通用而且不合适,而且文件类型的检查也没法做
r.Body = http.MaxBytesReader(w, r.Body, 32<<20+512)
解决方案二
自己逐步解析
r.Body = http.MaxBytesReader(w, r.Body, 32<<20+1024)
reader, err := r.MultipartReader()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// parse text field
text := make([]byte, 512)
p, err := reader.NextPart()
// one more field to parse, EOF is considered as failure here
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if p.FormName() != "text_field" {
http.Error(w, "text_field is expected", http.StatusBadRequest)
return
}
_, err = p.Read(text)
if err != nil && err != io.EOF {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// parse file field
p, err = reader.NextPart()
if err != nil && err != io.EOF {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if p.FormName() != "file_field" {
http.Error(w, "file_field is expected", http.StatusBadRequest)
return
}
buf := bufio.NewReader(p)
sniff, _ := buf.Peek(512)
contentType := http.DetectContentType(sniff)
if contentType != "application/zip" {
http.Error(w, "file type not allowed", http.StatusBadRequest)
return
}
f, err := ioutil.TempFile("", "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer f.Close()
var maxSize int64 = 32 << 20
lmt := io.MultiReader(buf, io.LimitReader(p, maxSize - 511))
written, err := io.Copy(f, lmt)
if err != nil && err != io.EOF {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if written > maxSize {
os.Remove(f.Name())
http.Error(w, "file size over limit", http.StatusBadRequest)
return
}
提示:
只在POST主体中获取前两个部分,处理程序将期望text_field然后file_field
使用bufio.Reader包装part reader(先查看512字节)断言文件类型
使用io.LimitReader限制文件大小(使用1个字节的偏移量来查看part reader是否还有一些数据)
文件已经上传到服务器翻译,服务器接受上传的优化 翻译+源码分析相关推荐
- 《恋上数据结构第1季》哈希表介绍以及从源码分析哈希值计算
哈希表(Hash Table) 引出哈希表 哈希表(Hash Table) 哈希冲突(Hash Collision) JDK1.8的哈希冲突解决方案 哈希函数 如何生成 key 的哈希值 Intege ...
- Java游戏服务器成长之路——弱联网游戏篇(源码分析)
http://blog.csdn.net/hjcenry/article/details/50530472 前段时间由于公司的一款弱联网游戏急着上线,没能及时分享,现在基本做的差不多,剩下的就是测试阶 ...
- HTTP服务器的本质:tinyhttpd源码分析及拓展
已经有一个月没有更新博客了,一方面是因为平时太忙了,另一方面是想积攒一些干货进行分享.最近主要是做了一些开源项目的源码分析工作,有c项目也有python项目,想提升一下内功,今天分享一下tinyhtt ...
- FFmpeg简述,源码分析,录制/压缩/水印/剪切/旋转/滤镜/美颜/上传视频等(CPU软编码和解码)
> ffmpeg源码分析 ffmpeg源码简析(一)结构总览- https://blog.csdn.net/Louis_815/article/details/79621056 FFmpeg的库 ...
- Thrift异步IO服务器源码分析
http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html 最近在使用 libevent 开发项目,想起之前写 ...
- SRS(simple-rtmp-server)流媒体服务器源码分析--启动
SRS(simple-rtmp-server)流媒体服务器源码分析--系统启动 一.前言 小卒最近看SRS源码,随手写下博客,其一为了整理思路,其二也是为日后翻看方便.如果不足之处,请指教! 首先总结 ...
- redis源码分析 -- cs结构之服务器
服务器与客户端是如何交互的 redis客户端向服务器发送命令请求,服务器接收到客户端发送的命令请求之后,读取解析命令,并执行命令,同时将命令执行结果返回给客户端. 客户端与服务器交互的代码流程如下图所 ...
- Linux项目实战C++轻量级Web服务器源码分析TinyWebServer
目录 文章简介 一. 先跑起来项目 二.再看项目核心 三.逐个击破!立下flag 文章简介 TinyWebServer是Linux下C++轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的 ...
- kazoo源码分析:服务器交互的实现细节
kazoo源码分析 kazoo-2.6.1 kazoo客户端与服务器概述 上文start概述中,只是简单的概述了kazoo客户端初始化之后,调用了start方法,本文继续详细的了解相关的细节. kaz ...
- SRS流媒体服务器源码分析(一):Rtmp publish流程
1.线程模型 srs使用了state-threads协程库,是单线程多协程模型. 这个协程的概念类似于lua的协程,都是单线程中可以创建多个协程.而golang中的goroutine协程是多线程并发的 ...
最新文章
- 夜宵虽好,可不要贪“杯”哦
- Ping一下Github,确认本地DNS无法解析方法
- C语言——常见的字符串函数+内存操作函数的介绍及实现
- Navisworks API 简单二次开发 (自定义工具条)
- C语言学习之分别用while、for 编写程序,计算2*4*6*......*100的值
- docker学习笔记(三)docker中的网络
- MachineLearning(12)- RNN-LSTM-tf.nn.rnn_cell
- 工作总结:日志打印的15个建议
- 斗地主AI算法——第十三章の主动出牌(2)
- 创建Struts 2简单应用的流程
- Atitit jpql ast总结v2 t025.docx 目录 1.1. 多select字段 1 1.2. 多个and条件 (ok) 2 1.3. Select 字段函数(聚合等) 2 1.4. [
- mysql date 索引_SQL 中 IS NULL 可以走索引
- java 使用JEP 进行节点计算
- MySQL数据库简单使用
- [常用工具] 搜索引擎的常用技巧总结
- 用友U9 BP不执行
- 可视化丨福尔摩斯探案集的数据分析
- vue 日历签到组件
- 优维EasyOps®全平台又一波新功能上线,操作体验更带劲
- 2020年jQuery笔试题汇总整理