Go 限制FormFile中的文件大小

Go 限制FormFile中的文件大小,go,Go,我允许用户使用FormFile上传文件。我应该在什么时候检查文件大小是否过大。当我这样做的时候 file, header, fileErr := r.FormFile("file") 已创建文件对象。那么,我已经承担了读取整个文件的费用了吗 在请求结构和r.Header.Get(“内容长度”)字符串中有r.ContentLength int64字段。这可能会有所帮助。调用FormFile调用,它将解析整个请求体,在将内容存储到临时文件之前,默认情况下最多使用32M。在调用

我允许用户使用FormFile上传文件。我应该在什么时候检查文件大小是否过大。当我这样做的时候

 file, header, fileErr := r.FormFile("file")
已创建文件对象。那么,我已经承担了读取整个文件的费用了吗


在请求结构和
r.Header.Get(“内容长度”)字符串中有
r.ContentLength int64
字段。这可能会有所帮助。

调用
FormFile
调用,它将解析整个请求体,在将内容存储到临时文件之前,默认情况下最多使用32M。在调用
FormFile
之前,您可以自己调用
ParseMultiPartForm
来确定要消耗多少内存,但正文仍将被解析

客户端可能会在中提供一个
内容长度
头,您可以在其中使用,但这取决于客户端

如果要限制传入请求的大小,请在解析任何正文之前,将
request.Body
包装在处理程序中。

用于限制从请求读取的字节数。在调用ParseMultiPartForm或FormFile之前,请执行此行:

 r.Body = http.MaxBytesReader(w, r.Body, max)
其中
r
*http.Request
w
http.Response

MaxBytesReader限制为整个请求正文而不是单个文件读取的字节数。当只有一个文件上载时,对请求正文大小的限制可以很好地近似于对文件大小的限制。如果需要对一个或多个文件强制执行特定限制,请将MaxByteReader限制设置为足够大,以容纳所有预期的请求数据,并检查每个文件

当违反http.MaxByteReader限制时,服务器停止从请求中读取,并在处理程序返回后关闭连接

如果要限制使用的内存量而不是请求正文大小,请在调用
r.FormFile()
之前调用。这将使用多达
maxMemory
字节的文件部分,其余部分存储在磁盘上的临时文件中。此调用不限制从客户端读取的字节总数或上载文件的大小

检查标头不起作用,原因有两个:

  • 未为分块请求正文设置内容长度
  • 服务器可以读取整个请求正文以支持连接保持活动。违反MaxByteReader限制是确保服务器停止读取请求正文的唯一方法

一些人建议依赖
内容长度
标题,我必须警告您不要使用它。此标头可以是任何数字,因为客户端可以更改它,而不考虑实际文件大小

使用,因为:

MaxByteReader可防止客户端意外或恶意 发送大请求并浪费服务器资源

以下是一个例子:

r.Body = http.MaxBytesReader(w, r.Body, 2 * 1024 * 1024) // 2 Mb
clientFile, handler, err := r.FormFile(formDataKey)
if err != nil {
    log.Println(err)
    return
}

如果您的请求正文大于2MB,您将看到如下内容:
multipart:NextPart:http:request body过大
http.MaxBytesReader()
需要一个
io.ReadCloser
,因此应该传递
r.body
r.body=http.MaxBytesReader(w,r.body,max)
这将限制总请求(包括所有字段+标题+文件组合)。如果只想限制每个文件(而不是文件数),请使用。请记住,您可能需要在一个请求中安全地防止攻击者上载100个不同的10MB文件。内容长度可能会被恶意用户篡改,我不会使用它,因为net/http服务器将请求体上的读取限制为内容长度头中指定的长度,恶意客户端通过指定较小的内容长度不会获得任何好处。也就是说,MaxBytesReader是一个不错的选择。