¿Por qué la carga de archivos ~2,5 MiB o mayor causa de un restablecimiento de la conexión?

0

Pregunta

Estamos tratando de implementar la subida de la imagen a través de peticiones POST. También queremos limitar las imágenes a ~1,0 MiB. Funciona bien en imágenes más pequeñas, pero nada ~2,5 MiB o mayor hace que la conexión a restablecer. También parece enviar varias solicitudes después de la primera para el mismo controlador.

principal.ir a:

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 salida cuando se carga un ~2,4 archivo MiB

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

También muestra la "petición demasiado grande" en el navegador

Salida al cargar ~2,5 archivo MiB

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

El navegador muestra que la conexión se restablece

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

Mejor respuesta

3

El cliente está tratando de enviar datos al servidor. El servidor no es la lectura de los datos, es sólo mirar las cabeceras y el cierre de la conexión. El cliente es interpretar esto como "la conexión se restablezca". Esto está fuera de su control.

En lugar de comprobar el encabezado, el encabezado de la mentira, el uso http.MaxBytesReader para leer el contenido real, pero el error si es demasiado 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")
}

Ver Cómo el proceso de carga de archivos en Ir para obtener más detalles.

2021-11-23 20:55:11

Esto parece funcionar a ampliar y realmente se adapte a nuestras necesidades. Sin embargo todavía hace un restablecimiento de la conexión con una imagen del tamaño suficiente como este, así que por ejemplo, si yo quería criar a los MAX_UPLOAD_SIZE a 20 << 20 por alguna razón que no sería capaz de cargar cualquier cosa de ese tamaño.
urist

También pensé en la r.ContentLength podría ser utilizado como una comprobación rápida antes de que los archivos son incluso subido a todos, aunque sé que podría ser falso. Supongo que se podría implementar esto en el lado del cliente de las cosas
urist

Creo que he entendido por qué el restablecimiento de la conexión de mi comentario de arriba, usted necesita para comenzar a utilizar los datos (por ejemplo, con r.FormFile), de lo contrario se acaba de parar y volver, y cerrar la conexión una vez que empieza a ser molesto por la constante de datos enviados por el cliente.
urist

En otros idiomas

Esta página está en otros idiomas

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