一般的做法

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. 《恋上数据结构第1季》哈希表介绍以及从源码分析哈希值计算

    哈希表(Hash Table) 引出哈希表 哈希表(Hash Table) 哈希冲突(Hash Collision) JDK1.8的哈希冲突解决方案 哈希函数 如何生成 key 的哈希值 Intege ...

  2. Java游戏服务器成长之路——弱联网游戏篇(源码分析)

    http://blog.csdn.net/hjcenry/article/details/50530472 前段时间由于公司的一款弱联网游戏急着上线,没能及时分享,现在基本做的差不多,剩下的就是测试阶 ...

  3. HTTP服务器的本质:tinyhttpd源码分析及拓展

    已经有一个月没有更新博客了,一方面是因为平时太忙了,另一方面是想积攒一些干货进行分享.最近主要是做了一些开源项目的源码分析工作,有c项目也有python项目,想提升一下内功,今天分享一下tinyhtt ...

  4. FFmpeg简述,源码分析,录制/压缩/水印/剪切/旋转/滤镜/美颜/上传视频等(CPU软编码和解码)

    > ffmpeg源码分析 ffmpeg源码简析(一)结构总览- https://blog.csdn.net/Louis_815/article/details/79621056 FFmpeg的库 ...

  5. Thrift异步IO服务器源码分析

    http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html 最近在使用 libevent 开发项目,想起之前写 ...

  6. SRS(simple-rtmp-server)流媒体服务器源码分析--启动

    SRS(simple-rtmp-server)流媒体服务器源码分析--系统启动 一.前言 小卒最近看SRS源码,随手写下博客,其一为了整理思路,其二也是为日后翻看方便.如果不足之处,请指教! 首先总结 ...

  7. redis源码分析 -- cs结构之服务器

    服务器与客户端是如何交互的 redis客户端向服务器发送命令请求,服务器接收到客户端发送的命令请求之后,读取解析命令,并执行命令,同时将命令执行结果返回给客户端. 客户端与服务器交互的代码流程如下图所 ...

  8. Linux项目实战C++轻量级Web服务器源码分析TinyWebServer

    目录 文章简介 一. 先跑起来项目 二.再看项目核心 三.逐个击破!立下flag 文章简介 TinyWebServer是Linux下C++轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的 ...

  9. kazoo源码分析:服务器交互的实现细节

    kazoo源码分析 kazoo-2.6.1 kazoo客户端与服务器概述 上文start概述中,只是简单的概述了kazoo客户端初始化之后,调用了start方法,本文继续详细的了解相关的细节. kaz ...

  10. SRS流媒体服务器源码分析(一):Rtmp publish流程

    1.线程模型 srs使用了state-threads协程库,是单线程多协程模型. 这个协程的概念类似于lua的协程,都是单线程中可以创建多个协程.而golang中的goroutine协程是多线程并发的 ...

最新文章

  1. 夜宵虽好,可不要贪“杯”哦
  2. Ping一下Github,确认本地DNS无法解析方法
  3. C语言——常见的字符串函数+内存操作函数的介绍及实现
  4. Navisworks API 简单二次开发 (自定义工具条)
  5. C语言学习之分别用while、for 编写程序,计算2*4*6*......*100的值
  6. docker学习笔记(三)docker中的网络
  7. MachineLearning(12)- RNN-LSTM-tf.nn.rnn_cell
  8. 工作总结:日志打印的15个建议
  9. 斗地主AI算法——第十三章の主动出牌(2)
  10. 创建Struts 2简单应用的流程
  11. Atitit jpql ast总结v2 t025.docx 目录 1.1. 多select字段 1 1.2. 多个and条件 (ok) 2 1.3. Select 字段函数(聚合等) 2 1.4. [
  12. mysql date 索引_SQL 中 IS NULL 可以走索引
  13. java 使用JEP 进行节点计算
  14. MySQL数据库简单使用
  15. [常用工具] 搜索引擎的常用技巧总结
  16. 用友U9 BP不执行
  17. 可视化丨福尔摩斯探案集的数据分析
  18. vue 日历签到组件
  19. 优维EasyOps®全平台又一波新功能上线,操作体验更带劲
  20. 2020年jQuery笔试题汇总整理

热门文章

  1. 前端学习(1647):前端系列实战课程之选项卡实现js思路
  2. java学习(33):巩固练习
  3. STM32 FreeRTOS USART DMA空闲中断和消息队列的使用
  4. stylus之选择器(Selectors)
  5. 分页的limit_分页场景(limit,offset)为什么会慢
  6. Python之操作HBASE数据库
  7. 截取地址栏URL参数
  8. 【转】使用Jmeter针对ActiveMQ JMS Point To Point压力测试
  9. Android上传文件至服务器(转)
  10. rocketmq 初探(三)