Saluti, compagni. Bellissimo sui miei server di combattimento
Gli amici mi hanno chiesto di creare una farm di sviluppo per loro e, invece di trascinare loro i miei modelli specifici, mi sono ricordato di un progetto interessante
Ovviamente, prima di scavare nei sorgenti, ho guardato dove Chrome estrae l'archivio zip generato con le configurazioni, e lì mi aspettava un indirizzo che inizia con "blob:", oops. È già diventato chiaro che il servizio non genera nulla lungo il percorso, infatti è tutto fatto da js. Infatti, l'archivio zip viene generato dal client, dal browser e dallo stesso JavaScript. Quelli. il bello è che il progetto
Dopo aver biforcato il progetto, ho iniziato a pensare a quali fossero le mie opzioni. Il compito è stato complicato dal fatto che non volevo discostarmi dalla condizione che il progetto rimanesse un puro front-end, senza back-end. Naturalmente, la soluzione più semplice sarebbe quella di richiamare nodejs e forzarlo a generare un archivio con configurazioni utilizzando collegamenti diretti.
In realtà non c'erano molte opzioni. Più precisamente, me ne è venuto in mente solo uno. Dobbiamo impostare le configurazioni e ottenere un collegamento che possiamo copiare sulla console del server per ottenere un archivio zip.
Diversi file di testo nell'archivio zip risultante pesavano parecchio, letteralmente pochi kilobyte. La soluzione ovvia era prendere la stringa base64 dall'archivio zip generato e gettarla nel buffer, mentre sul server con il comando nella console
echo 'base64string' | base64 --decode > config.zip
potremmo creare questo stesso file zip.
Nelle risorse del progetto vediamo un metodo per generare un archivio zip:
$scope.downloadZip = function() {
var zip = new JSZip();
var sourceCodes = $window.document.querySelectorAll('main .file .code.source');
for (var i = 0; i < sourceCodes.length; i++) {
var sourceCode = sourceCodes[i];
var name = sourceCode.dataset.filename;
var content = sourceCode.children[0].children[0].innerText;
if (!$scope.isSymlink() && name.match(/^sites-available//)) {
name = name.replace(/^sites-available//, 'sites-enabled/');
}
zip.file(name, content);
if (name.match(/^sites-available//)) {
zip.file(name.replace(/^sites-available//, 'sites-enabled/'), '../' + name, {
unixPermissions: parseInt('120755', 8),
});
}
}
zip.generateAsync({
type: 'blob',
platform: 'UNIX',
}).then(function(content) {
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
});
gtag('event', $scope.getDomains().join(','), {
event_category: 'download_zip',
});
};
tutto è abbastanza semplice, utilizzando la libreria
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
dove contenuto è l'oggetto BLOB risultante dell'archivio zip.
Ok, tutto quello che dovevo fare era aggiungere un altro pulsante accanto e quando ci cliccavo sopra, non avrei salvato l'archivio zip risultante nel browser, ma avrei ottenuto da esso il codice base64. Dopo aver armeggiato un po', ho ottenuto 2 metodi, invece di un solo downloadZip:
$scope.downloadZip = function() {
generateZip(function (content) {
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
});
gtag('event', $scope.getDomains().join(','), {
event_category: 'download_zip',
});
};
$scope.downloadBase64 = function() {
generateZip(function (content) {
var reader = new FileReader();
reader.readAsDataURL(content);
reader.onloadend = function() {
var base64 = reader.result.replace(/^data:.+;base64,/, '');
// в переменной base64 как раз нужный мне zip архив в виде base64 строки
}
});
gtag('event', $scope.getDomains().join(','), {
event_category: 'download_base64',
});
};
Come avrai notato, ho spostato la generazione dell'archivio zip stesso nel metodo generateZip privato e così via. Questo è AngularJS e l'autore stesso si attiene ai callback e non lo ha implementato tramite promesse. downloadZip eseguiva comunque saveAs come output, mentre downloadBase64 faceva qualcosa di leggermente diverso. Creiamo un oggetto FileReader che ci è arrivato in html5 ed è già abbastanza
position: absolute;
z-index: -1;
opacity: 0;
che mi ha permesso sia di nascondere l'elemento alla vista sia di lasciarlo effettivamente sulla pagina. Voilà, l'attività è stata completata, quando ho fatto clic sul pulsante, nel buffer è stata inserita una riga come questa:
echo 'base64string' | base64 --decode > config.zip
che ho semplicemente incollato nella console del server e ho subito ricevuto un archivio zip con tutte le configurazioni.
E, ovviamente, ho inviato una pull request all'autore, perché... il progetto è attivo e vivace, mi piacerebbe vedere gli aggiornamenti dell'autore e avere un mio pulsante) Per chi fosse interessato, eccolo qui
Buon sviluppo a tutti)
Fonte: habr.com