在FormFile中限制文件大小

huangapple go评论75阅读模式
英文:

Limiting file size in FormFile

问题

我正在使用FormFile让用户上传文件。在什么时候应该检查文件大小是否过大?当我执行以下代码时:

 file, header, fileErr := r.FormFile("file")

一个文件对象已经被创建。那么我已经读取整个文件的成本了吗?

https://golang.org/pkg/net/http#Request.FormFile

英文:

I'm letting users upload a file using FormFile. At what point should I check if the file size is too large. When I do

 file, header, fileErr := r.FormFile("file")

A file object is already created. So have I incurred the cost of reading in the entire file already?

https://golang.org/pkg/net/http#Request.FormFile

答案1

得分: 19

使用http.MaxBytesReader来限制从请求中读取的字节数。在调用ParseMultiPartForm或FormFile之前,执行以下代码:

r.Body = http.MaxBytesReader(w, r.Body, max)

其中,r*http.Requestwhttp.Response

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

当超过http.MaxBytesReader的限制时,服务器在处理程序返回后停止从请求中读取,并关闭连接。

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

检查request Content-Length标头不起作用,原因有两个:

  • 对于分块请求体,内容长度未设置。
  • 服务器可能会读取整个请求体以支持连接保持活动。超过MaxBytesReader限制是确保服务器停止读取请求体的唯一方法。
英文:

Use http.MaxBytesReader to limit the number of bytes read from the request. Before calling ParseMultiPartForm or FormFile, execute this line:

 r.Body = http.MaxBytesReader(w, r.Body, max)

where r is the *http.Request and w is the http.Response.

MaxBytesReader limits the bytes read for the entire request body and not an individual file. A limit on the request body size can be a good approximation of a limit on the file size when there's only one file upload. If you need to enforce a specific limit for one or more files, then set the MaxBytesReader limit large enough for all expected request data and check FileHeader.Size for each file.

When the http.MaxBytesReader limit is breached, the server stops reading from the request and closes the connection after the handler returns.

If you want to limit the amount of memory used instead of the request body size, then call r.ParseMultipartForm(maxMemory) before calling r.FormFile(). This will use up to maxMemory bytes for file parts, with the remainder stored in temporary files on disk. This call does not limit the total number of bytes read from the client or the size of an uploaded file.

Checking the request Content-Length header does not work for two reasons:

  • The content length is not set for chunked request bodies.
  • The server may read the entire request body to support connection keep-alive. Breaching the MaxBytesReader limit is the only way to ensure that the server stops reading the request body.

答案2

得分: 13

有些人建议依赖于Content-Length头部,但我必须警告你不要使用它。这个头部可以是任意数字,因为客户端可以更改它,而不考虑实际文件大小。

使用MaxBytesReader,因为:

> MaxBytesReader可以防止客户端意外或恶意地发送大请求,从而浪费服务器资源。

以下是一个示例:

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
}

如果你的请求体超过2 Mb,你会看到类似这样的错误信息:multipart: NextPart: http: request body too large

英文:

Some people are suggesting to rely on Content-Length header and I have to warn you not to use it at all. This header can be any number because it can be changed by a client regardless of the actual file size.

Use MaxBytesReader because:

> MaxBytesReader prevents clients from accidentally or maliciously
> sending a large request and wasting server resources.

Here is an example:

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
}

If your request body is bigger than 2 Mb, you will see something like this: multipart: NextPart: http: request body too large

答案3

得分: 5

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

客户端可以在multipart.FileHeader中提供Content-Length头,你可以使用它,但这取决于客户端。

如果你想限制传入请求的大小,在处理程序中在解析任何请求体之前,可以使用MaxBytesReader包装request.Body

英文:

Calling FormFile calls ParseMultiPartForm, which will parse the entire request body, using up to 32M by default before storing the contents in temporary files. You can call ParseMultiPartForm yourself before calling FormFile to determine how much memory to consume, but the body will still be parsed.

Th client may provide a Content-Length header in the multipart.FileHeader which you could use, but that is dependent on the client.

If you want to limit the incoming request size, wrap the request.Body with MaxBytesReader in your handler before parsing any of the Body.

答案4

得分: 1

你的请求结构中有一个 r.ContentLength int64 字段和一个 r.Header.Get("Content-Length") string 方法。也许这可以帮到你。

英文:

You have r.ContentLength int64 field in request struct and r.Header.Get("Content-Length") string method. Maybe that can help.

huangapple
  • 本文由 发表于 2015年1月22日 01:33:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/28073395.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定