🐛 Fix corrupt zip and remove project download on server

This commit is contained in:
brunosimon
2017-12-25 17:49:53 +01:00
parent 3d93205750
commit 2620b00ffe
23 changed files with 148 additions and 60 deletions
+5 -5
View File
@@ -2,7 +2,7 @@
const slug = require('slug')
const Files = require('./files.js')
const Chat = require('./chat.js')
const AdmZip = require('adm-zip')
const JSZip = require('jszip')
const glob = require('glob')
const fs = require('fs')
const path = require('path')
@@ -72,8 +72,8 @@ class Project
// Search files with glob
const files = glob.sync(this.path + '/**', { dot: true })
// Create a zip file
const zip = new AdmZip()
// // Create a zip file
const zip = new JSZip()
// Add files to zip
for(const _file of files)
@@ -85,12 +85,12 @@ class Project
{
const basename = path.basename(_file)
const relativePath = _file.replace(basename, '').replace(this.path, '')
zip.addLocalFile(_file, relativePath)
zip.file(`${relativePath}${basename}`, fs.readFileSync(_file))
}
}
// Create and return zip buffer
this.zipBuffer = zip.toBuffer()
this.zipBuffer = zip.generateNodeStream({ type: 'nodebuffer', streamFiles: true })
this.zipNeedsUpdate = false
// Debug
+4
View File
@@ -18,6 +18,10 @@ class Projects
// Connection event
this.projectsSocket.on('connection', (socket) =>
{
// // Send the config to the new socket
socket.emit('config', { domain: this.config.domain, server: this.config.server })
// Send the projects update to all users
this.projectsSocket.emit('update_projects', this.describe())
if(this.config.debug >= 1)
+10 -7
View File
@@ -109,13 +109,16 @@ class Site
// Get zip buffer
const zipBuffer = _project.getZipBuffer()
// Send
response.writeHead(200, {
'Content-Type': 'application/zip',
'Content-Length': zipBuffer.length
})
response.write(zipBuffer, 'binary')
response.end(null, 'binary')
// Set finename
const date = new Date()
const hours = `${date.getHours() < 10 ? '0' : ''}${date.getHours()}`
const minutes = `${date.getMinutes() < 10 ? '0' : ''}${date.getMinutes()}`
const seconds = `${date.getSeconds() < 10 ? '0' : ''}${date.getSeconds()}`
const name = `${_project.slug}_${hours}-${minutes}-${seconds}.zip`
response.setHeader('Content-disposition', `attachment; filename=${name}`)
zipBuffer.pipe(response)
})
this.express.use('/' + _project.slug + '/files', express.static(_project.path))
+60 -5
View File
@@ -58,11 +58,6 @@
}
}
},
"adm-zip": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz",
"integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E="
},
"after": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
@@ -2435,6 +2430,11 @@
"is-symbol": "1.0.1"
}
},
"es6-promise": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
"integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y="
},
"escape-html": {
"version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
@@ -4236,6 +4236,11 @@
"integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=",
"dev": true
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -4675,6 +4680,48 @@
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true
},
"jszip": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
"integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
"requires": {
"core-js": "2.3.0",
"es6-promise": "3.0.2",
"lie": "3.1.1",
"pako": "1.0.6",
"readable-stream": "2.0.6"
},
"dependencies": {
"core-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
"integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU="
},
"pako": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
"integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "0.10.31",
"util-deprecate": "1.0.2"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -4716,6 +4763,14 @@
"type-check": "0.3.2"
}
},
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"requires": {
"immediate": "3.0.6"
}
},
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+2 -2
View File
@@ -23,14 +23,15 @@
},
"homepage": "https://github.com/brunosimon/keppler",
"dependencies": {
"adm-zip": "^0.4.7",
"chokidar": "^1.7.0",
"colors": "^1.1.2",
"diff": "^3.3.0",
"express": "^4.15.3",
"glob": "^7.1.2",
"helmet": "^3.8.1",
"html-entities": "^1.2.1",
"ip": "^1.1.5",
"jszip": "^3.1.5",
"mime": "^1.3.6",
"minimatch": "^3.0.4",
"node-notifier": "^5.1.2",
@@ -40,7 +41,6 @@
"socket.io-client": "^2.0.3",
"vue": "^2.3.3",
"vuex": "^2.3.1",
"html-entities": "^1.2.1",
"yargs": "^8.0.2"
},
"devDependencies": {
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><title>Keppler</title><meta name=viewport content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><link class=favicon rel=icon type=image/png href=""><link href=/static/css/app.d379c533b0023617002453dec20e90b9.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.740d3494c804055a5113.js></script><script type=text/javascript src=/static/js/app.6410af1d45da75742280.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><title>Keppler</title><meta name=viewport content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><link class=favicon rel=icon type=image/png href=""><link href=/static/css/app.d379c533b0023617002453dec20e90b9.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.dccd405c2f8ce5d06dc2.js></script><script type=text/javascript src=/static/js/app.03226a35957b0c5066f6.js></script></body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s<t.length;s++)a=t[s],o[a]&&l.push(o[a][0]),o[a]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,i);l.length;)l.shift()();if(i)for(s=0;s<i.length;s++)f=n(n.s=i[s]);return f};var t={},o={1:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var i=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"static/js/"+e+"."+{0:"6410af1d45da75742280"}[e]+".js";var a=setTimeout(r,12e4);return u.onerror=u.onload=r,i.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.740d3494c804055a5113.js.map
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s<t.length;s++)a=t[s],o[a]&&l.push(o[a][0]),o[a]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,i);l.length;)l.shift()();if(i)for(s=0;s<i.length;s++)f=n(n.s=i[s]);return f};var t={},o={1:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var i=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"static/js/"+e+"."+{0:"03226a35957b0c5066f6"}[e]+".js";var a=setTimeout(r,12e4);return u.onerror=u.onload=r,i.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.dccd405c2f8ce5d06dc2.js.map
File diff suppressed because one or more lines are too long
@@ -19,6 +19,11 @@ export default
computed:
{
serverConfig()
{
return this.$store.state.serverConfig
},
project()
{
return this.$store.state.projects.current
@@ -5,6 +5,8 @@
<!-- Favicon -->
<favicon></favicon>
<div v-if="serverConfig">
<!-- Header -->
<a class="application-header" href="#" @click.prevent="onHeaderClick">
<img class="element background" src="../../../static/svg/header-background.svg" alt="">
@@ -22,4 +24,6 @@
<!-- Project -->
<project v-if="project"></project>
</div>
</div>
+6 -2
View File
@@ -40,14 +40,18 @@ export default
const projectsUrl = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/projects`
this.projectsSocket = socketIoClient(projectsUrl)
this.projectsSocket.on('connect', () =>
this.projectsSocket.on('connect', (data) =>
{
// console.log('projects connected')
})
this.projectsSocket.on('config', (data) =>
{
this.$store.commit('updateServerConfig', data)
})
this.projectsSocket.on('update_projects', (data) =>
{
this.$store.commit('updateUrl', data.domain)
this.$store.commit('updateProjects', data.all)
})
},
+1 -1
View File
@@ -20,7 +20,7 @@ export default
{
downloadUrl()
{
return `${this.$store.state.url}/${this.$store.state.projects.current.slug}/files/${this.content.path.full}`
return `${this.$store.state.serverConfig.domain}/${this.$store.state.projects.current.slug}/files/${this.content.path.full}`
},
downloadDataUri()
+1 -1
View File
@@ -30,7 +30,7 @@ export default
quote: () => quotes[Math.floor(quotes.length * Math.random())],
url()
{
return this.$store.state.url
return this.$store.state.serverConfig.domain
}
},
+1 -1
View File
@@ -21,7 +21,7 @@ export default
{
downloadUrl()
{
return `${this.$store.state.url}/${this.project.slug}/download`
return `${this.$store.state.serverConfig.domain}/${this.project.slug}/download`
},
project()
+6 -1
View File
@@ -11,6 +11,11 @@ export default
computed:
{
serverConfig()
{
return this.$store.state.serverConfig
},
projects()
{
return this.$store.state.projects.all
@@ -34,7 +39,7 @@ export default
return ''
}
return `${this.$store.state.url}/${this.currentProject.slug}/download`
return `${this.$store.state.serverConfig.domain}/${this.currentProject.slug}/download`
}
},
@@ -18,7 +18,7 @@
</div>
</div>
<a class="download" :href="downloadUrl" download>
<a v-if="!serverConfig.server" class="download" :href="downloadUrl" download="test.zip">
<img class="icon default" src="../../../static/svg/download.svg" alt="">
<img class="icon hover" src="../../../static/svg/download-hover.svg" alt="">
<tooltip position="right">Download the whole project</tooltip>
+3 -3
View File
@@ -17,15 +17,15 @@ export default new Vuex.Store({
state:
{
url: '',
serverConfig: null,
scrollbarWidth: 0
},
mutations:
{
updateUrl(state, data)
updateServerConfig(state, data)
{
state.url = data
state.serverConfig = data
},
updateScrollbarWidth(state, data)
@@ -0,0 +1,8 @@
body {
margin:0;
padding:0;
}
.toto .tata > span {
background:url('kikoo.png') top left repeat-x;
}

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB