如果文件太大,Golang 文件上传:关闭连接

13

我希望允许上传文件。使用Go处理服务器请求。如果他们正在尝试上传的文件太大,我想发送一个“文件太大”的响应。在整个文件被上传之前(带宽),我想这样做。

我正在使用以下代码片段,但它只在客户端完成上传后发送响应。它保存了一个5kB的文件。

const MaxFileSize = 5 * 1024
// This feels like a bad hack...
if r.ContentLength > MaxFileSize {
    if flusher, ok := w.(http.Flusher); ok {
        response := []byte("Request too large")
        w.Header().Set("Connection", "close")
        w.Header().Set("Content-Length", fmt.Sprintf("%d", len(response)))
        w.WriteHeader(http.StatusExpectationFailed)
        w.Write(response)
        flusher.Flush()
    }
    conn, _, _ :=  w.(http.Hijacker).Hijack()
    conn.Close()
    return
}

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

err := r.ParseMultipartForm(1024)
if err != nil {
    w.Write([]byte("File too large"));
    return
}

file, header, err := r.FormFile("file")
if err != nil {
    panic(err)
}

dst, err := os.Create("upload/" + header.Filename)
defer dst.Close()
if err != nil { 
    panic(err)
}

written, err := io.Copy(dst, io.LimitReader(file, MaxFileSize))
if err != nil {
    panic(err)
}

if written == MaxFileSize {
    w.Write([]byte("File too large"))
    return
}
w.Write([]byte("Success..."))
1个回答

20

大多数客户端在完成请求之前不会阅读响应。服务器返回错误不会导致这些客户端停止编写。

net/http服务器支持100继续状态码。要使用此功能,服务器应该在读取请求正文之前先响应一个错误:

func handler(w http.ResponseWriter, r *http.Request) {
  if r.ContentLength > MaxFileSize {
     http.Error(w, "request too large", http.StatusExpectationFailed)
     return
  }
  r.Body = http.MaxBytesReader(w, r.Body, MaxFileSize)
  err := r.ParseMultipartForm(1024)

  // ... continue as before

如果客户端发送了"Expect: 100-continue"头部,那么客户端应该在写入请求体之前等待100 continue状态。当服务器应用程序读取请求体时,net/http服务器会自动发送100 continue状态。如果在读取请求之前回复错误,服务器可以阻止客户端写入请求体。

net/http客户端不支持100 continue状态

如果客户端没有发送expect头部且服务器应用程序从请求处理程序返回而没有完全读取请求体,则net/http服务器会读取并丢弃最多256 << 10字节的请求体。如果没有读取整个请求体,服务器将关闭连接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接