Proč nahrávání souborů ~2,5 MiB nebo větší, protože připojení obnovit?

0

Otázka

Snažíme se realizovat obrazu nahrávání přes POST požadavky. Chceme také omezit obrázky na ~1,0 MiB. To funguje na menší obrázky, ale nic, ~2,5 MiB nebo větší způsobí, že připojení resetovat. Zdá se také, chcete-li odeslat více žádostí po prvním stejného psovoda.

hlavní.go:

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>

Výstup při nahrávání ~2,4 MiB souboru

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

To také ukazuje, "žádost o příliš velký" v prohlížeči

Výstup při nahrávání ~2,5 MiB souboru

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

Prohlížeč nyní zobrazuje, že připojení bylo resetováno

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

Nejlepší odpověď

3

Klient se pokouší odeslat data na server. Na serveru je čtení dat, je to jen při pohledu na záhlaví a ukončení spojení. Klient je takto "připojení bylo resetováno". To je mimo vaši kontrolu.

Místo kontroly záhlaví, záhlaví může ležet, používat http.MaxBytesReader číst skutečný obsah, ale chyba, pokud je příliš velký.

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

Vidět , Jak se proces nahrávání souborů v Cestách pro více detailů.

2021-11-23 20:55:11

Toto vypadá, že práce na rozšíření a skutečně vyhovuje našim potřebám. Nicméně to stále způsobuje obnovení připojení s dostatečně velký obraz, jako je tento, takže například, pokud bych chtěl zvýšit na MAX_UPLOAD_SIZE 20 << 20 z nějakého důvodu jsem nebyl schopný nahrát něco z té velikosti.
urist

Také jsem si myslel, že r.ContentLength by mohly být použity jako rychlá kontrola před všechny soubory jsou nahrané i na všechny, i když vím, že by to mohlo být falešné. Myslím, že můžete provést v klientské věci
urist

Myslím, že jsem přišel na to, proč obnovit připojení z mé výše uvedené komentáře, které potřebujete, aby skutečně začít používat údaje (například s r.FormFile), jinak to bude jen zastavit a vrátit se, a ukončit připojení, jakmile to začne dostat naštvaný o konstantní data odesílána klientem.
urist

V jiných jazycích

Tato stránka je v jiných jazycích

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