一尘不染

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

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..."))

阅读 663

收藏
2020-07-02

共1个答案

一尘不染

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

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

如果客户端发送了“期望:100-继续”标头,则客户端应在写入请求正文之前等待100继续状态。当服务器应用程序读取请求正文时,net /
http服务器自动发送100继续状态。服务器可以通过在读取请求之前以错误答复来阻止客户端编写请求主体。

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

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

2020-07-02