Riallacciandomi al precedente articolo ([php] Configurare php.ini per l’upload dei file) voglio approfondire il problema del caricamento di file di grosse dimensioni su server che utilizzano PHP, Apache e nginx (nel mio caso specifico anche Plesk).
Gli errori che possono sorgere sono difatti innumerevoli e spesso apparentemente senza senso.
Cominciamo riepilogando il necessario per quello che riguarda il PHP. Come spiegato nel precedente articolo, assicuriamoci di avere una configurazione simile alla seguente nel file php.ini
1 2 3 4 5 6 |
upload_max_filesize = 512M post_max_size = 513M max_file_uploads = 500 memory_limit = 1024MB max_execution_time = 1200 max_input_time = 1200 |
In questo caso sto supponendo che caricheremo file fino a 512MB.
Per quanto riguarda il PHP ci dobbiamo assicurare che la quantità di memorie allocabile sia compatibile con la dimensione dei file da caricare e che lo sia anche il tempo di esecuzione.
Con un tempo di 1200 secondi si suppone che l’upload avverrà ad un minimo di 0,43MB/s. Questo significa che parte del caricamento dipende anche dalla velocità di upload del client, che potrebbe non essere sufficientemente alta da permettere al server di terminare l’operazione nei tempi consentiti.
Per inciso ricordiamoci che le classiche connessioni ADSL 20 Mega hanno upload che si aggirano attorno a 1 Mbit, ovvero 0,12 MB/s. Questo significa che il tempo di esecuzione dovrebbe essere per lo meno di 4.300 secondi (approssimando per eccesso).
Detto tutto questo si potrebbe incorrere in altri problemi, come ad esempio, lato client: Failed to load resource: net::ERR_HTTP2_PROTOCOL_ERROR
Se si sta tentando di gestire l’upload tramite javascript e si incorre in questo errore, esso nulla ha a che fare con il protocollo HTTP/2 (e tanto meno è utile tornare al HTTP/1.1 o simili), ma è legato al fatto che la pagina non invia una risposta corretta. La risposta non viene inviata correttamente perché ad interrompere l’upload possono essere Apache oppure nginx.
Controllando il log del server si potrebbe trovare infatti un errore simile al seguente: 19855#0: *532 client intended to send too large body: 180584796 bytes
In questo caso sto cercando di caricare circa 172MB di file ed nginix blocca l’operazione.
Nel mio caso specifico posso verificare la cosa, confrontando su Windows la dimensione dei file che sto tentando di inviare al server con un unico upload.
Si può notare come la dimensione bloccata sia leggermente più grande dei file in upload, perché, come già discusso nel precedente articolo, il corpo che viene inviato al server contiene anche informazioni aggiuntive che vanno al di là dei singoli file che si stanno caricando.
A questo punto dobbiamo intervenire su nginx aggiungendo l’istruzione:
1 |
client_max_body_size 512m; |
La configurazione predefinite di nginx sarebbe di 1m, mentre sotto Plesk è di 128m.
Questo parametro può essere modificato all’interno del file /etc/nginx/nginx.conf
Per farlo su Plesk procediamo nel modo seguente (è anche spiegato nella vademecum ufficiale, anche se ci sono delle piccole incongruenze):
- Colleghiamoci via SSH al Server con Plesk
- Creiamo un file di configurazione aggiuntivo a cui aggiungeremo l’istruzione precedente:
echo 'client_max_body_size 128m;' > /etc/nginx/conf.d/aa_client_max_body.conf
- Verifichiamo se esiste il file
/usr/local/psa/admin/conf/panel.ini
- Se non dovesse esistere creiamolo copiandolo dal file predefinito:
cp /usr/local/psa/admin/conf/panel.ini.sample /usr/local/psa/admin/conf/panel.ini
- Aggiungiamo l’impostazione per la massima dimensione del corpo:
echo -e "[webserver]\n nginxClientMaxBodySize = 512m\n" >> /usr/local/psa/admin/conf/panel.ini
- Modifichiamo i permessi:
chmod 644 /usr/local/psa/admin/conf/panel.ini
- Riconfiguriamo il tutto:
plesk sbin httpdmng --reconfigure-all
- Riavviamo nginx:
service nginx restart
- Assicuriamoci che su tutti i webserver sia configurato il parametro giusto:
nginx -T | grep client_max_body_size
- Nel caso non lo fosse possiamo usare l’istruzione, per riconfigurare il tutto:
plesk repair web -y -v
In generale dovremmo assicurarci che, rispetto ai parametri suddetti, nelle configurazioni di nginx, sotto la voce server
, compaiano i seguenti due valori:
1 2 3 4 5 6 7 8 9 |
server { ... client_max_body_size 512m; proxy_read_timeout 1200; ... } |
Questi valori dovrebbero essere in linea (o superiori) con quelli scelti per il PHP.
Infine dobbiamo verificare che anche Apache consenta l’esecuzione dell’upload. Nel caso specifico potrebbero esserci due parametri ad influenzarlo: FcgidMaxRequestLen e LimitRequestBody
Impostiamoli nel modo seguente:
1 2 |
FcgidMaxRequestLen 512000000 LimitRequestBody 512000000 |
Se abbiamo configurato tutto correttamente dovremmo essere in grado di caricare i file come definito all’inizio.