Skip to content

Commit 8576b35

Browse files
author
sasdf
committed
changed app export import method
I add a random string to the tmpfolder's path so that you can export two project at the same time. And it compress and download at the same time *WARING* I've changed the file structure in the export zip file, so the older export file cannot be used.
1 parent 3b05ce7 commit 8576b35

File tree

1 file changed

+87
-70
lines changed

1 file changed

+87
-70
lines changed

coder-base/apps/coder/app.js

Lines changed: 87 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ exports.settings={};
4141

4242
exports.get_routes = [
4343
{ path:'/', handler:'index_handler' },
44-
{ path: /^\/export\/download\/(\w+\.zip)$/, handler:'export_download_handler' },
44+
{ path: /^\/export\/download\/(\w+)\.zip$/, handler:'export_download_handler' },
4545
];
4646

4747

@@ -155,19 +155,80 @@ exports.export_download_handler = function( req, res, pathmatches ) {
155155
return;
156156
}
157157

158-
var exportfile = 'appexport.zip';
159158
var path = process.cwd();
160-
if ( !fs.existsSync( path + '/tmp/' + exportfile ) ) {
159+
if ( !fs.existsSync( path + '/apps/' + exportname + '/app.js' ) ) {
161160
res.json({
162161
status: "error",
163-
error: "Export file doesn't exist"
162+
error: "Application doesn't exist"
164163
});
165164
return;
166165
}
166+
167+
var success = true;
168+
var exportkey = uuid( 16 );
169+
var uuidfolder = path + '/tmp/' + exportkey;
170+
try { forceRemoveDir( uuidfolder ); } catch (e) {}
171+
try { fs.mkdirSync( uuidfolder ); } catch (e) { success = false; }
172+
var tmpfolder = uuidfolder + '/' + exportname;
173+
try { fs.mkdirSync( tmpfolder ); } catch (e) { success = false; }
174+
try { fs.mkdirSync( tmpfolder + '/app' ); } catch (e) { success = false; }
175+
try { fs.mkdirSync( tmpfolder + '/static' ); } catch (e) { success = false; }
176+
try { fs.mkdirSync( tmpfolder + '/static/css' ); } catch (e) { success = false; }
177+
try { fs.mkdirSync( tmpfolder + '/static/js' ); } catch (e) { success = false; }
178+
try { fs.mkdirSync( tmpfolder + '/static/media' ); } catch (e) { success = false; }
179+
try { fs.mkdirSync( tmpfolder + '/views' ); } catch (e) { success = false; }
167180

168-
res.download( path + '/tmp/' + exportfile, exportname );
181+
if ( !success ) {
182+
res.json({
183+
status: "error",
184+
error: "Cannot create export directory."
185+
});
186+
return;
187+
}
169188

170189

190+
//app node.js file
191+
copyFile( path + '/apps/' + exportname + '/app.js', tmpfolder + '/app/app.js' );
192+
//app meta.json file
193+
copyFile( path + '/apps/' + exportname + '/meta.json', tmpfolder + '/app/meta.json' );
194+
//html view
195+
copyFile( path + '/views/apps/' + exportname + '/index.html', tmpfolder + '/views/index.html' );
196+
//css data
197+
copyFile( path + '/static/apps/' + exportname + '/css/index.css', tmpfolder + '/static/css/index.css' );
198+
//index.js file
199+
copyFile( path + '/static/apps/' + exportname + '/js/index.js', tmpfolder + '/static/js/index.js' );
200+
201+
var mediadir = path + "/static/apps/" + exportname + "/media/";
202+
var mediafiles = fs.readdirSync( mediadir );
203+
for ( var x in mediafiles ) {
204+
var filename = mediafiles[x];
205+
var info = fs.statSync( mediadir + filename );
206+
if ( typeof info !== 'undefined' && info && info.isFile() ) {
207+
copyFile( mediadir + filename, tmpfolder + '/static/media/' + filename );
208+
}
209+
}
210+
211+
res.writeHead( 200, {
212+
'Content-Type': 'application/octet-stream'
213+
,'Content-disposition': 'attachment; filename=' + exportname + '.zip'
214+
} );
215+
216+
var zip = spawn( 'zip', [ '-r', '-', '.' ], { cwd: uuidfolder } );
217+
zip.stdout.on( 'data', function ( data ){
218+
res.write( data );
219+
} );
220+
zip.on( 'close', function ( code ) {
221+
res.end();
222+
zip = null;
223+
try { forceRemoveDir( uuidfolder ); } catch (e) {}
224+
} );
225+
req.on( 'close', function () {
226+
if ( zip !== null ) {
227+
if ( zip ) { zip.kill('SIGTERM'); }
228+
try { forceRemoveDir( uuidfolder ); } catch (e) {}
229+
}
230+
} );
231+
171232
};
172233

173234

@@ -191,14 +252,16 @@ exports.api_app_import_handler = function( req, res, pathmatches ) {
191252

192253
var path = process.cwd();
193254
var success = true;
194-
var importkey = 'appimport'; //TODO: maybe this should be random and auto-cleaned
255+
var importkey = uuid( 16 );
195256
var tmpfolder = path + '/tmp/' + importkey;
257+
var uuidfolder = tmpfolder;
196258
try { forceRemoveDir( tmpfolder ); } catch (e) {}
197259
try { fs.mkdirSync( tmpfolder ); } catch (e) { success = false; }
198260

199261

200262
var completeImport = function() {
201263

264+
tmpfolder += '/' + (fs.readdirSync( tmpfolder ))[0];
202265
if ( !fs.existsSync( tmpfolder + '/app/meta.json' )
203266
|| !fs.existsSync( tmpfolder + '/app/app.js')
204267
|| !fs.existsSync( tmpfolder + '/views/index.html')
@@ -270,6 +333,7 @@ exports.api_app_import_handler = function( req, res, pathmatches ) {
270333
}
271334
}
272335

336+
try { forceRemoveDir( uuidfolder ); } catch (e) {}
273337

274338
res.json({
275339
status: "success",
@@ -279,17 +343,19 @@ exports.api_app_import_handler = function( req, res, pathmatches ) {
279343
};
280344

281345

282-
var uploadPath = tmpfolder + '/appimport.zip';
346+
var uploadPath = tmpfolder + '/' + importkey + '.zip';
283347
fs.readFile(req.files['import_file'].path, function (err, data) {
284348
fs.writeFile(uploadPath, data, function (err) {
285349

286-
var unzip = spawn('unzip', ['appimport.zip'], { cwd: tmpfolder });
350+
var unzip = spawn('unzip', [importkey + '.zip'], { cwd: tmpfolder });
287351
unzip.stdout.on('data', function (data) {
288352
});
289353
unzip.stderr.on('data', function (data) {
290354
});
291355
unzip.on('exit', function (code) {
356+
fs.unlinkSync( uploadPath );
292357
if(code !== 0) {
358+
try { forceRemoveDir( tmpfolder ); } catch (e) {}
293359
res.json({
294360
status: "error",
295361
error: "unzip error: " + code
@@ -328,68 +394,9 @@ exports.api_app_export_handler = function( req, res, pathmatches ) {
328394
return;
329395
}
330396

331-
var success = true;
332-
var exportkey = 'appexport'; //TODO: maybe this should be random and auto-cleaned
333-
var tmpfolder = path + '/tmp/' + exportkey;
334-
try { forceRemoveDir( tmpfolder ); } catch (e) {}
335-
try { fs.unlinkSync( path + '/tmp/' + exportkey + '.zip' ); } catch (e) {}
336-
try { fs.mkdirSync( tmpfolder ); } catch (e) { success = false; }
337-
try { fs.mkdirSync( tmpfolder + '/app' ); } catch (e) { success = false; }
338-
try { fs.mkdirSync( tmpfolder + '/static' ); } catch (e) { success = false; }
339-
try { fs.mkdirSync( tmpfolder + '/static/css' ); } catch (e) { success = false; }
340-
try { fs.mkdirSync( tmpfolder + '/static/js' ); } catch (e) { success = false; }
341-
try { fs.mkdirSync( tmpfolder + '/static/media' ); } catch (e) { success = false; }
342-
try { fs.mkdirSync( tmpfolder + '/views' ); } catch (e) { success = false; }
343-
344-
if ( !success ) {
345-
res.json({
346-
status: "error",
347-
error: "Cannot create export directory."
348-
});
349-
return;
350-
}
351-
352-
353-
//app node.js file
354-
copyFile( path + '/apps/' + apptoexport + '/app.js', tmpfolder + '/app/app.js' );
355-
//app meta.json file
356-
copyFile( path + '/apps/' + apptoexport + '/meta.json', tmpfolder + '/app/meta.json' );
357-
//html view
358-
copyFile( path + '/views/apps/' + apptoexport + '/index.html', tmpfolder + '/views/index.html' );
359-
//css data
360-
copyFile( path + '/static/apps/' + apptoexport + '/css/index.css', tmpfolder + '/static/css/index.css' );
361-
//index.js file
362-
copyFile( path + '/static/apps/' + apptoexport + '/js/index.js', tmpfolder + '/static/js/index.js' );
363-
364-
var mediadir = path + "/static/apps/" + apptoexport + "/media/";
365-
var mediafiles = fs.readdirSync( mediadir );
366-
for ( var x in mediafiles ) {
367-
var filename = mediafiles[x];
368-
var info = fs.statSync( mediadir + filename );
369-
if ( typeof info !== 'undefined' && info && info.isFile() ) {
370-
copyFile( mediadir + filename, tmpfolder + '/static/media/' + filename );
371-
}
372-
}
373-
374-
var zip = spawn('zip', ['-r', '../appexport.zip', '.', '-i', '*'], { cwd: tmpfolder });
375-
zip.stdout.on('data', function (data) {
376-
//console.log('coder::api_app_export_handler zip: ' + data );
377-
});
378-
zip.stderr.on('data', function (data) {
379-
//console.log('coder::api_app_export_handler zip error: ' + data );
380-
});
381-
zip.on('exit', function (code) {
382-
if(code !== 0) {
383-
res.json({
384-
status: "error",
385-
error: "zip error: " + code
386-
});
387-
} else {
388-
res.json({
389-
status: "success",
390-
file: apptoexport + ".zip"
391-
});
392-
}
397+
res.json({
398+
status: "success",
399+
file: apptoexport + ".zip"
393400
});
394401

395402
};
@@ -493,3 +500,13 @@ var forceRemoveDir = function( path ) {
493500
//util.log( 'remove directory ' + path );
494501
fs.rmdirSync( path );
495502
};
503+
504+
var uuid = function ( num ) {
505+
var text = "";
506+
var possible = "abcdefghijklmnopqrstuvwxyz0123456789";
507+
508+
for( var i=0; i < num; i++ )
509+
text += possible.charAt(Math.floor(Math.random() * possible.length));
510+
511+
return text;
512+
}

0 commit comments

Comments
 (0)