++ fix backup
This commit is contained in:
@@ -20,8 +20,23 @@
|
|||||||
};
|
};
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
{{--
|
||||||
|
Il comportamento del riquadro di ripristino sta in un componente Alpine
|
||||||
|
registrato piu' sotto (@script), non in un x-data lungo.
|
||||||
|
|
||||||
|
Il motivo e' concreto: un attributo HTML finisce alla prima virgoletta
|
||||||
|
doppia, comprese quelle dentro un commento. Con il codice nell'attributo, un
|
||||||
|
banale // un generico "errore" ha chiuso l'attributo a meta' e ha riversato
|
||||||
|
tutto il resto del JavaScript a video come testo. Dentro un blocco <script>
|
||||||
|
virgolette e apostrofi non hanno alcun potere di rompere il markup.
|
||||||
|
|
||||||
|
Le stringhe usano comunque i backtick: e' la forma in cui un apostrofo
|
||||||
|
italiano non richiede alcun accorgimento.
|
||||||
|
--}}
|
||||||
<div class="space-y-6"
|
<div class="space-y-6"
|
||||||
x-data="{
|
x-data="{
|
||||||
|
{{-- maxUploadKb() e' in kilobyte; file.size e' in byte. --}}
|
||||||
|
maxByte: {{ \App\Http\Controllers\Settings\BackupController::maxUploadKb() }} * 1000,
|
||||||
zipSelezionato: '',
|
zipSelezionato: '',
|
||||||
uploadInCorso: false,
|
uploadInCorso: false,
|
||||||
uploadPercento: 0,
|
uploadPercento: 0,
|
||||||
@@ -38,37 +53,47 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const password = this.passwordAzzeramento;
|
const password = this.passwordAzzeramento;
|
||||||
// Svuotato subito: se la password è sbagliata si ridigita, e nel
|
// Svuotata subito: se e' sbagliata si ridigita, e intanto non resta
|
||||||
// frattempo non resta nel campo di una scheda lasciata aperta.
|
// nel campo di una scheda lasciata aperta.
|
||||||
this.passwordAzzeramento = '';
|
this.passwordAzzeramento = '';
|
||||||
// this.$wire e non $wire: dentro un metodo di x-data la forma
|
|
||||||
// esplicita e' l'unica su cui si possa contare.
|
|
||||||
this.$wire.confermaAzzeramento(password);
|
this.$wire.confermaAzzeramento(password);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Il file e' troppo grande? Si scopre qui, prima di caricare.
|
|
||||||
*
|
|
||||||
* Superato il tetto, e' nginx a chiudere la connessione a meta'
|
* Superato il tetto, e' nginx a chiudere la connessione a meta'
|
||||||
* trasferimento: la barra si pianta a una percentuale qualsiasi e non
|
* trasferimento: la barra si pianta a una percentuale qualsiasi e non
|
||||||
* arriva nessun evento utile, quindi la pagina resta muta con l'aria di
|
* arriva nessun evento utile, quindi la pagina resta muta con l'aria di
|
||||||
* essersi bloccata. Controllare la dimensione prima di partire rende
|
* essersi bloccata. Controllare prima di partire rende quel caso un
|
||||||
* quel caso un messaggio immediato invece di un'attesa senza fine.
|
* messaggio immediato invece di un'attesa senza fine.
|
||||||
*/
|
*/
|
||||||
zipTroppoGrande(file) {
|
zipTroppoGrande(file) {
|
||||||
const maxByte = {{ \App\Http\Controllers\Settings\BackupController::maxUploadKb() }} * 1000;
|
if (!file || file.size <= this.maxByte) {
|
||||||
|
|
||||||
if (!file || file.size <= maxByte) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mb = (n) => (n / 1000000).toFixed(0);
|
const mb = (n) => (n / 1000000).toFixed(0);
|
||||||
this.erroreUpload = `Il pacchetto pesa ${mb(file.size)} MB e supera il limite di ${mb(maxByte)} MB accettato dal server. `
|
|
||||||
+ `Per archivi piu' grandi usa il ripristino dai volumi descritto nel README, oppure chiedi di alzare il limite.`;
|
this.erroreUpload = `Il pacchetto pesa ${mb(file.size)} MB e supera il limite di `
|
||||||
|
+ `${mb(this.maxByte)} MB accettato dal server. Per archivi più grandi alza MAX_UPLOAD_MB `
|
||||||
|
+ `nel .env (serve un redeploy) oppure usa il ripristino dai volumi descritto nel README.`;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fileScelto(event) {
|
||||||
|
this.erroreUpload = '';
|
||||||
|
this.uploadPercento = 0;
|
||||||
|
|
||||||
|
const file = event.target.files[0];
|
||||||
|
this.zipSelezionato = file
|
||||||
|
? `${file.name} (${(file.size / 1000000).toFixed(1)} MB)`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
this.zipTroppoGrande(file);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
inviaRipristino(event) {
|
inviaRipristino(event) {
|
||||||
const form = event.target;
|
const form = event.target;
|
||||||
const file = form.querySelector('input[name=backupZip]').files[0];
|
const file = form.querySelector('input[name=backupZip]').files[0];
|
||||||
@@ -77,8 +102,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = new FormData(form);
|
|
||||||
|
|
||||||
this.erroreUpload = '';
|
this.erroreUpload = '';
|
||||||
this.uploadInCorso = true;
|
this.uploadInCorso = true;
|
||||||
this.uploadPercento = 0;
|
this.uploadPercento = 0;
|
||||||
@@ -88,9 +111,9 @@
|
|||||||
xhr.setRequestHeader('Accept', 'application/json');
|
xhr.setRequestHeader('Accept', 'application/json');
|
||||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||||
|
|
||||||
// Un caricamento che non si muove per cinque minuti e' fermo, non
|
// Un caricamento fermo da cinque minuti e' fermo, non lento: senza
|
||||||
// lento: senza questo non scatterebbe piu' nessun evento e la
|
// questo non scatterebbe piu' alcun evento e la pagina resterebbe
|
||||||
// pagina resterebbe in attesa per sempre.
|
// in attesa per sempre.
|
||||||
xhr.timeout = 300000;
|
xhr.timeout = 300000;
|
||||||
|
|
||||||
xhr.upload.addEventListener('progress', (e) => {
|
xhr.upload.addEventListener('progress', (e) => {
|
||||||
@@ -101,8 +124,13 @@
|
|||||||
|
|
||||||
xhr.addEventListener('load', () => {
|
xhr.addEventListener('load', () => {
|
||||||
this.uploadInCorso = false;
|
this.uploadInCorso = false;
|
||||||
|
|
||||||
let payload = {};
|
let payload = {};
|
||||||
try { payload = JSON.parse(xhr.responseText || '{}'); } catch (e) { payload = {}; }
|
try {
|
||||||
|
payload = JSON.parse(xhr.responseText || '{}');
|
||||||
|
} catch (e) {
|
||||||
|
payload = {};
|
||||||
|
}
|
||||||
|
|
||||||
if (xhr.status >= 200 && xhr.status < 300 && payload.operation_id) {
|
if (xhr.status >= 200 && xhr.status < 300 && payload.operation_id) {
|
||||||
this.uploadPercento = 100;
|
this.uploadPercento = 100;
|
||||||
@@ -113,11 +141,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Qualsiasi esito diverso: la barra torna a zero, perche'
|
// La barra torna a zero: lasciarla dov'era farebbe credere che
|
||||||
// lasciarla dov'era farebbe credere che il ripristino sia
|
// il ripristino sia partito.
|
||||||
// partito. Il codice HTTP entra nel messaggio: 413 e 419 non
|
|
||||||
// producono un corpo JSON, quindi senza di esso resterebbe solo
|
|
||||||
// un generico "errore" che non dice cosa fare.
|
|
||||||
this.uploadPercento = 0;
|
this.uploadPercento = 0;
|
||||||
this.erroreUpload = this.messaggioErrore(xhr.status, payload);
|
this.erroreUpload = this.messaggioErrore(xhr.status, payload);
|
||||||
});
|
});
|
||||||
@@ -125,25 +150,29 @@
|
|||||||
xhr.addEventListener('error', () => {
|
xhr.addEventListener('error', () => {
|
||||||
this.uploadInCorso = false;
|
this.uploadInCorso = false;
|
||||||
this.uploadPercento = 0;
|
this.uploadPercento = 0;
|
||||||
this.erroreUpload = 'Errore di rete durante il caricamento: connessione interrotta dal server. '
|
this.erroreUpload = `Errore di rete durante il caricamento: connessione interrotta dal `
|
||||||
+ 'Succede tipicamente quando il pacchetto supera il limite accettato.';
|
+ `server. Succede tipicamente quando il pacchetto supera il limite accettato.`;
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.addEventListener('timeout', () => {
|
xhr.addEventListener('timeout', () => {
|
||||||
this.uploadInCorso = false;
|
this.uploadInCorso = false;
|
||||||
this.uploadPercento = 0;
|
this.uploadPercento = 0;
|
||||||
this.erroreUpload = 'Il caricamento non ha risposto entro 5 minuti ed e\\' stato interrotto.';
|
this.erroreUpload = `Il caricamento non ha risposto entro 5 minuti ed è stato interrotto.`;
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.addEventListener('abort', () => {
|
xhr.addEventListener('abort', () => {
|
||||||
this.uploadInCorso = false;
|
this.uploadInCorso = false;
|
||||||
this.uploadPercento = 0;
|
this.uploadPercento = 0;
|
||||||
this.erroreUpload = 'Caricamento annullato.';
|
this.erroreUpload = `Caricamento annullato.`;
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.send(formData);
|
xhr.send(new FormData(form));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 413 e 419 non hanno un corpo JSON: senza il codice HTTP nel messaggio
|
||||||
|
* resterebbe un generico errore che non dice cosa fare.
|
||||||
|
*/
|
||||||
messaggioErrore(status, payload) {
|
messaggioErrore(status, payload) {
|
||||||
if (payload.message) {
|
if (payload.message) {
|
||||||
return payload.message;
|
return payload.message;
|
||||||
@@ -154,15 +183,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status === 413) {
|
if (status === 413) {
|
||||||
return 'Il pacchetto e\\' troppo grande per il server (413). Alza client_max_body_size in nginx e post_max_size in PHP, oppure usa il ripristino dai volumi.';
|
return `Il pacchetto è troppo grande per il server (413). Alza MAX_UPLOAD_MB nel .env e rifai il deploy, oppure usa il ripristino dai volumi.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status === 419) {
|
if (status === 419) {
|
||||||
return 'Sessione scaduta durante il caricamento. Ricarica la pagina e riprova.';
|
return `Sessione scaduta durante il caricamento. Ricarica la pagina e riprova.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status === 0) {
|
if (status === 0) {
|
||||||
return 'Il server ha chiuso la connessione durante il caricamento, senza rispondere. Di solito significa che il pacchetto supera il limite accettato.';
|
return `Il server ha chiuso la connessione durante il caricamento, senza rispondere. Di solito significa che il pacchetto supera il limite accettato.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `Errore durante il caricamento del pacchetto (HTTP ${status}).`;
|
return `Errore durante il caricamento del pacchetto (HTTP ${status}).`;
|
||||||
@@ -341,13 +370,7 @@
|
|||||||
subito che il file e' fuori limite evita di aspettare un
|
subito che il file e' fuori limite evita di aspettare un
|
||||||
caricamento destinato a essere tagliato. --}}
|
caricamento destinato a essere tagliato. --}}
|
||||||
<input name="backupZip" type="file" accept=".zip,application/zip"
|
<input name="backupZip" type="file" accept=".zip,application/zip"
|
||||||
x-on:change="
|
x-on:change="fileScelto($event)"
|
||||||
erroreUpload = '';
|
|
||||||
uploadPercento = 0;
|
|
||||||
const f = $event.target.files[0];
|
|
||||||
zipSelezionato = f ? f.name + ' (' + (f.size / 1000000).toFixed(1) + ' MB)' : '';
|
|
||||||
if (f) zipTroppoGrande(f);
|
|
||||||
"
|
|
||||||
class="block w-full text-sm text-gray-600 file:mr-3 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-medium file:bg-red-50 file:text-red-700 hover:file:bg-red-100">
|
class="block w-full text-sm text-gray-600 file:mr-3 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-medium file:bg-red-50 file:text-red-700 hover:file:bg-red-100">
|
||||||
<p class="mt-1 text-xs text-gray-500">
|
<p class="mt-1 text-xs text-gray-500">
|
||||||
Dimensione massima accettata: {{ \App\Http\Controllers\Settings\BackupController::maxUploadMb() }} MB.
|
Dimensione massima accettata: {{ \App\Http\Controllers\Settings\BackupController::maxUploadMb() }} MB.
|
||||||
|
|||||||
Reference in New Issue
Block a user