React
Upload con progresso reale: cosa misurare
Il progresso di un upload arriva dai byte dichiarati dal browser, non da un timer: onUploadProgress misura l'invio, non la fine del lavoro.
In sintesi
- Il progresso reale viene dall'evento upload di XMLHttpRequest, non da un timer.
- fetch non espone l'avanzamento dell'invio: serve XMLHttpRequest o axios.
- 100% dell'invio non significa elaborazione finita: mostra una seconda fase.
Il progresso di un upload si legge dai byte che il browser dichiara di aver inviato, con l'evento upload.onprogress di XMLHttpRequest: un timer che avanza non misura nulla.
Perché fetch non lo espone
Con fetch il corpo della richiesta è uno stream opaco e non esiste un evento di avanzamento dell'invio: il download si legge a pezzi, l'upload no. Servono XMLHttpRequest o una libreria che lo incapsula, come axios, distribuito con licenza MIT.
Il codice che misura
function carica(file, onProgress) {
const body = new FormData();
body.append("file", file);
return axios.post("/api/upload", body, {
onUploadProgress: (e) => onProgress(Math.round((e.loaded / e.total) * 100)),
});
}
La percentuale è loaded diviso total: misura l'invio dei byte, non l'elaborazione del file sul server.
Le trappole
- 100% non vuol dire finito: l'invio è completo, la risposta può arrivare molto dopo.
- total a zero: con
Transfer-Encoding: chunkedil totale manca e la barra resta indeterminata. - Più file: si sommano i byte di tutti i file, non le percentuali.
- Annullamento:
AbortControllerferma la richiesta e l'evento smette di arrivare.
Installazione
npm i axios
L'installazione aggiunge una sola dipendenza MIT; onUploadProgress funziona nei browser che espongono XMLHttpRequest, quindi non nei test con jsdom.
Record vivi nel catalogo
Tre componenti di caricamento file: file-upload-card, file-upload-2 e avatar-uploader. Per sfogliare per categoria parti da 111.985 componenti.
La limitazione
La barra misura l'invio, non l'esito: se il server accoda il file, l'utente vede 100% e attesa. Per un progresso onesto serve una seconda fase, con un id di job da interrogare.
Dove continuare
La route handler per i file è in upload con Next.js; il confronto fra i due schemi di campo è in form controllati e non; la scelta di framework è in Vue 3 vs React.
Domande frequenti
Perché la barra arriva a 100% e non finisce?
Perché misura l'invio, non l'elaborazione. Mostra uno stato separato per l'attesa della risposta.
fetch supporta il progresso di upload?
No, non per il corpo inviato. Con fetch leggi il download a pezzi, non i byte in uscita.
Come testo la barra?
Simuli un evento di progresso sul finto XMLHttpRequest: jsdom non invia byte e non emette eventi veri.
Serve axios per forza?
No. XMLHttpRequest basta; axios incapsula la stessa API e aggiunge una dipendenza MIT.
Il tempo residuo è affidabile?
No. I byte sono un dato reale, la stima del tempo dipende da una velocità che cambia.