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

时间:2014-10-15 21:11:37

标签: http upload go

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

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

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 个答案:

答案 0 :(得分:15)

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

net / http服务器支持100 continue status。要使用此功能,服务器应用程序应在读取请求正文之前响应错误:

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继续状态。当服务器应用程序读取请求主体时,net / http服务器自动发送100继续状态。在读取请求之前,服务器可以通过回复错误来阻止客户端编写请求正文。

net / http客户端does not support the 100 continue status

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