Por que não faz upload de arquivos ~2,5 MiB ou maior causar uma redefinição de conexão?

0

Pergunta

Estamos tentando implementar o upload de imagens através de solicitações POST. Nós também queremos limitar as imagens para ~1,0 MiB. Ele funciona bem em imagens menores, mas nada de ~2,5 MiB ou maior faz com que a reposição da ligação. Parece também para enviar vários pedidos depois do primeiro para o mesmo processador.

principal.ir:

package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", uploadHandler)
    http.ListenAndServe("localhost:8080", nil)
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        postHandler(w, r)
        return
    } else {
        http.ServeFile(w, r, "index.html")
    }
}

func postHandler(w http.ResponseWriter, r *http.Request) {
    // Send an error if the request is larger than 1 MiB
    if r.ContentLength > 1<<20 {
        // if larger than ~2,5 MiB, this will print 2 or more times
        log.Println("File too large")
        // And this error will never arrive, instead a Connection reset
        http.Error(w, "response too large", http.StatusRequestEntityTooLarge)
        return
    }
    return
}

index.html:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <form method="POST" enctype="multipart/form-data">
      <input type="file" accept="image/*" name="profile-picture"><br>
      <button type="submit" >Upload</button>
  </form>
  </body>
</html>

De saída quando o upload de uma ~2,4 arquivo MiB

$ go run main.go
2021/11/23 22:00:14 File too large

Ele também mostra "a solicitação é muito grande" no navegador

De saída quando o upload de ~2,5 arquivo MiB

$ go run main.go
2021/11/23 22:03:25 File too large
2021/11/23 22:03:25 File too large

O navegador agora mostra que a conexão foi redefinida

go http
2021-11-23 20:06:27
1

Melhor resposta

3

O cliente está tentando enviar dados para o servidor. O servidor não está lendo os dados, é só olhar para os cabeçalhos e fechar a conexão. O cliente é interpretar isso como "a conexão foi redefinida". Isso está fora do seu controle.

Em vez de verificar o cabeçalho, o cabeçalho pode mentir, usar http.MaxBytesReader para ler o conteúdo real, mas o erro se ele é muito grande.

const MAX_UPLOAD_SIZE = 1<<20

func postHandler(w http.ResponseWriter, r *http.Request) {
    // Wrap the body in a reader that will error at MAX_UPLOAD_SIZE
    r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)

    // Read the body as normal. Check for an error.
    if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
        // We're assuming it errored because the body is too large.
        // There are other reasons it could error, you'll have to
        // look at err to figure that out.
        log.Println("File too large")
        http.Error(w, "Your file is too powerful", http.StatusRequestEntityTooLarge)
        return
    }

    fmt.Fprintf(w, "Upload successful")
}

Veja Como processo de upload de arquivos em Ir para mais detalhes.

2021-11-23 20:55:11

Isso parece funcionar de uma prorrogação e, na verdade, se adapte às nossas necessidades. No entanto, ele ainda provoca uma redefinição de conexão com um grande o suficiente imagem, como esta, por exemplo, se eu quiser aumentar o MAX_UPLOAD_SIZE para 20 << 20 por alguma razão eu não seria capaz de carregar qualquer coisa desse tamanho.
urist

Eu também pensei que a r.ContentLength pode ser usado como uma verificação rápida antes de quaisquer ficheiros são mesmo carregado a todos, apesar de eu saber que ele pode ser falsificado. Eu acho que você poderia implementar isso no lado do cliente de coisas
urist

Eu acho que eu descobri por que a conexão redefinida a partir do meu comentário acima, você precisa para começar a usar os dados (por exemplo, com r.FormFile), caso contrário ele só vai parar e voltar, e fechar a conexão, uma vez que começa a ficar irritado com a constante de dados a ser enviado pelo cliente.
urist

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................