Вітаю, товариші. На моїх бойових серверах чудовий
Друзі попросили підняти їм девелоперську ферму і замість тягнути їм свої специфічні шаблони я згадав про цікавий проект
Звичайно, перед тим, як колупати вихідники, я подивився звідки хром тягне згенерований zip архів з конфігами, а там на мене чекав адресу, що починається з «blob:», оппа. Вже стало зрозуміло, що під час сервіс нічого не генерує, за фактом, що це все робить js. Справді, архів zip генерує сам клієнт, браузер, javascript. Тобто. краса в тому, що проект
Зробивши форк проекту, я почав думати, які маю варіанти. Завдання ускладнювалося тим, що я не хотів відходити від умови, що проект повинен залишатися чистим front-end без будь-якого back-end. Звичайно, найпростіше рішення було б підтягнути nodejs і змусити його генерувати архів із конфігами за прямими посиланнями.
Варіантів, власне, було небагато. Точніше, на думку прийшов тільки один. Нам потрібно налаштувати конфіги та отримати посилання, яке зможемо скопіювати в консоль сервера, щоб отримати архів 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');
де вміст, це отриманий 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