Приветствую, товарищи. На моих боевых серверах прекрасный
Друзья попросили поднять им девелоперскую ферму и вместо того, чтобы тащить им свои специфические шаблоны, я вспомнил про интересный проект
Конечно, перед тем, как ковырять исходники, я посмотрел откуда хром тянет сгенеренный zip архив с конфигами, а там меня ждал адрес, начинающийся с «blob:», оппа. Уже стало понятно, что по ходу сервис ничего не генерирует, по факту, что это всё делает js. Действительно, zip архив генерирует сам клиент, браузер, javascript. Т.е. прелесть в том, что проект
Сделав форк проекта, я начал думать, какие у меня есть варианты. Задача усложнялось тем, что я не хотел отходить от условия, что проект должен оставаться чистым front-end, без какого-либо back-end. Конечно, самое простое решение было бы подтянуть nodejs и заставить его генерировать архив с конфигами по прямым ссылкам.
Вариантов, собственно, было не много. Точнее, в голову пришёл только один. Нам надо настроить конфиги и получить ссылку, которую сможем скопировать в консоль сервера, чтобы получить zip архив.
Несколько текстовых файлов в получаемом zip архиве весили совсем немного, буквально несколько килобайт. Очевидным решением было получить base64 строку из сгенерированного zip архива и кинуть её в буфер, тогда как на сервере командой в консоли
echo 'base64string' | base64 --decode > config.zip
мы могли бы создать этот самый zip файл.
В сурсах проекта мы видим метод генерации 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',
});
};
всё достаточно просто, с помощью библиотеки
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
где content, это полученный blob объект zip архива.
Ок, всё что мне надо было сделать, это добавить ещё одну кнопку рядом и при нажатии на неё не сохранять полученный zip архив в браузер, а получать из него base64 код. Немного пошаманив, я получил 2 метода, вместо одного 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',
});
};
Как вы могли заметить, генерацию самого zip архива я вынес в приватный метод generateZip, ну и т.к. это AngularJS, да и сам автор придерживается колбэков, не стал реализовывать его через промисы. downloadZip по прежнему на выходе делал saveAs, тогда как downloadBase64 делал немного другое. Мы создаём FileReader объект, пришедший к нам в html5 и вполне уже
position: absolute;
z-index: -1;
opacity: 0;
что позволило мне и скрыть элемент с глаз и по факту оставить его на странице. Вуаля, задача выполнена, при нажатии на мою кнопку, в буфер помещалась строка вида:
echo 'base64string' | base64 --decode > config.zip
которую я просто вставлял в консоль на сервере и тут же получал zip архив со всеми конфигами.
Ну и, конечно, я закинул pull request автору, т.к. проект активный и живой, мне хочется и обновления от автора видеть и свою кнопопчку иметь ) Кому интересно, вот
Всем бодрой разработки )
Источник: habr.com