์๋
ํ์ธ์, ๋์ง๋ค. ๋ด ์ ํฌ ์๋ฒ์์๋ ์๋ฆ๋ต์ต๋๋ค.
์น๊ตฌ๋ค์ด ๋์๊ฒ ๊ฐ๋ฐ ํ์ ์ค์ ํด ๋ฌ๋ผ๊ณ ๋ถํํ๊ณ , ๋ด ํน์ ํ
ํ๋ฆฟ์ ๋๋๊ทธํ๋ ๋์ ํฅ๋ฏธ๋ก์ด ํ๋ก์ ํธ๊ฐ ์๊ฐ๋ฌ์ต๋๋ค.
๋ฌผ๋ก , ์์ค๋ฅผ ํํค์น๊ธฐ ์ ์ Chrome์ด ๊ตฌ์ฑ๊ณผ ํจ๊ป ์์ฑ๋ zip ์์นด์ด๋ธ๋ฅผ ๊ฐ์ ธ์ค๋ ์์น๋ฅผ ์ดํด๋ณด์๋๋ฐ "blob:"๋ก ์์ํ๋ ์ฃผ์๊ฐ ๋๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์์์ต๋๋ค. ์๋น์ค๊ฐ ๋์ค์ ์๋ฌด ๊ฒ๋ ์์ฑํ์ง ์๋๋ค๋ ๊ฒ์ด ์ด๋ฏธ ๋ถ๋ช
ํด์ก์ต๋๋ค. ์ค์ ๋ก ๋ชจ๋ ์์
์ js์ ์ํด ์ํ๋ฉ๋๋ค. ์ค์ ๋ก zip ์์นด์ด๋ธ๋ ํด๋ผ์ด์ธํธ, ๋ธ๋ผ์ฐ์ ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ์์ฒด์ ์ํด ์์ฑ๋ฉ๋๋ค. ์ ๊ฒ๋ค. ์๋ฆ๋ค์์ ํ๋ก์ ํธ๊ฐ
ํ๋ก์ ํธ๋ฅผ ํฌํฌํ ํ, ๋๋ ๋ด ์ ํ์ด ๋ฌด์์ธ์ง ์๊ฐํ๊ธฐ ์์ํ์ต๋๋ค. ํ๋ก์ ํธ๊ฐ ๋ฐฑ์๋ ์์ด ์์ํ ํ๋ฐํธ์๋๋ก ์ ์ง๋์ด์ผ ํ๋ค๋ ์กฐ๊ฑด์์ ๋ฒ์ด๋๊ณ ์ถ์ง ์์๊ธฐ ๋๋ฌธ์ ์์
์ด ๋ณต์กํด์ก์ต๋๋ค. ๋ฌผ๋ก ๊ฐ์ฅ ๊ฐ๋จํ ํด๊ฒฐ์ฑ
์ nodejs๋ฅผ ๋์ด์ ์ง์ ๋งํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑ์ด ํฌํจ๋ ์์นด์ด๋ธ๋ฅผ ์์ฑํ๋๋ก ๊ฐ์ ํ๋ ๊ฒ์
๋๋ค.
์ฌ์ค ์ ํ์ ์ฌ์ง๊ฐ ๋ณ๋ก ์์์ด์. ๋ ์ ํํ๊ฒ๋ ๋ฑ ํ๋๋ง ๋ ์ฌ๋๋ค. zip ์์นด์ด๋ธ๋ฅผ ์ป์ผ๋ ค๋ฉด ๊ตฌ์ฑ์ ์ค์ ํ๊ณ ์๋ฒ ์ฝ์์ ๋ณต์ฌํ ์ ์๋ ๋งํฌ๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
๊ฒฐ๊ณผ zip ์์นด์ด๋ธ์ ํฌํจ๋ ์ฌ๋ฌ ํ
์คํธ ํ์ผ์ ๋ฌด๊ฒ๋ ๋ง ๊ทธ๋๋ก ๋ช ํฌ๋ก๋ฐ์ดํธ์ ๋ฌํ์ต๋๋ค. ํ์คํ ํด๊ฒฐ์ฑ
์ ์์ฑ๋ zip ์์นด์ด๋ธ์์ base64 ๋ฌธ์์ด์ ๊ฐ์ ธ์ ๋ฒํผ์ ๋ฃ๋ ๋์์ ์๋ฒ์์ ์ฝ์์ ๋ช
๋ น์ ์ฌ์ฉํ๋ ๊ฒ์ด์์ต๋๋ค.
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๋ zip ์์นด์ด๋ธ์ ๊ฒฐ๊ณผ blob ๊ฐ์ฒด์ ๋๋ค.
์ข์, ๋ด๊ฐ ํด์ผ ํ ์ผ์ ๊ทธ ์์ ๋ ๋ค๋ฅธ ๋ฒํผ์ ์ถ๊ฐํ๋ ๊ฒ๋ฟ์ด์๊ณ , ๊ทธ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๊ฒฐ๊ณผ zip ์์นด์ด๋ธ๋ฅผ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅํ์ง ์๊ณ ๊ทธ๋ก๋ถํฐ base64 ์ฝ๋๋ฅผ ๊ฐ์ ธ์์ต๋๋ค. ์ฝ๊ฐ์ ๋ ธ๋ ฅ ๋์ ํ๋์ 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์ธ๋ฐ ์์ฑ์ ์์ ์ด ์ฝ๋ฐฑ๋ง ๊ณ ์ํ๊ณ Promise๋ฅผ ํตํด ๊ตฌํํ์ง ์์์ต๋๋ค. downloadZip์ ์ฌ์ ํ โโsaveAs๋ฅผ ์ถ๋ ฅ์ผ๋ก ์ํํ์ง๋ง downloadBase64๋ ์ฝ๊ฐ ๋ค๋ฅธ ์์
์ ์ํํ์ต๋๋ค. ์ฐ๋ฆฌ๋ html5์์ ์ ๊ณต๋์๋ FileReader ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
position: absolute;
z-index: -1;
opacity: 0;
์ด๋ฅผ ํตํด ์์๋ฅผ ๋ณด๊ธฐ์์ ์จ๊ธฐ๊ณ ์ค์ ๋ก ํ์ด์ง์ ๊ทธ๋๋ก ๋ ์ ์์์ต๋๋ค. ์ง์, ์์ ์ด ์๋ฃ๋์์ต๋๋ค. ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ค์ด ๋ฒํผ์ ๋ฐฐ์น๋์์ต๋๋ค.
echo 'base64string' | base64 --decode > config.zip
์๋ฒ์ ์ฝ์์ ๊ฐ๋จํ ๋ถ์ฌ๋ฃ๊ณ ๋ชจ๋ ๊ตฌ์ฑ์ด ํฌํจ๋ zip ์์นด์ด๋ธ๋ฅผ ์ฆ์ ๋ฐ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฌผ๋ก , ์์ฑ์์๊ฒ ํ ๋ฆฌํ์คํธ๋ ๋ณด๋์ต๋๋ค. ์๋๋ฉด... ํ๋ก์ ํธ๊ฐ ํ๋ฐํ๊ณ ํ๋ฐํฉ๋๋ค. ์์ฑ์์ ์
๋ฐ์ดํธ๋ฅผ ํ์ธํ๊ณ ๋๋ง์ ๋ฒํผ์ ๊ฐ๊ณ ์ถ์ต๋๋ค.) ๊ด์ฌ ์๋ ๋ถ์ ์ฌ๊ธฐ๋ฅผ ํด๋ฆญํ์ธ์.
๋ชจ๋ ํ๋ณตํ ๋ฐ์ ๋์ธ์)
์ถ์ฒ : habr.com