yunkong2.js-controller/lib/zipFiles.js
2018-09-17 20:32:19 +08:00

366 lines
13 KiB
JavaScript

'use strict';
var JSZip;
var tools = require(__dirname + '/tools');
function _getAllFilesInDir(objects, id, name, options, callback, result) {
result = result || [];
objects.readDir(id, name, options, function (err, files) {
var count = 0;
var errors = [];
if (files) {
for (var f = 0; f < files.length; f++) {
if (files[f].isDir) {
count++;
_getAllFilesInDir(objects, id, name + '/' + files[f].file, options, function (err, _result) {
if (err) errors.push(err);
if (!--count) callback(errors.length ? errors : null, _result);
}, result);
} else {
result.push(name + '/' + files[f].file);
}
}
}
if (!count) callback(null, result);
});
}
function _addFile(objects, id, name, options, zip, files, callback) {
objects.readFile(id, name, options, function (err, data, mime) {
if (!zip) {
console.log(err);
callback('Cannot read file "' + name + '": ' + err, files);
} else {
// if handler installed
if (options.stringify) {
try {
data = options.stringify(name, data, options ? options.settings : null, files);
} catch (error) {
console.error('Cannot stringify file "' + name + '": ' + error);
if (!err) err = 'Cannot stringify file "' + name + '": ' + error;
}
}
var parts = name.split('/');
if (parts.length > 1) {
parts.shift();
name = parts.join('/');
}
zip.file(name, data);
setImmediate(function () {
callback(err, files);
});
}
});
}
// pack all files as zip and send it back
function readDirAsZip(objects, id, name, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
if (name[0] === '/') name = name.substring(1);
options = options || {};
var adapter = id;
if (adapter.indexOf('.') !== -1) {
adapter = id.split('.')[0];
}
// try to load processor of adapter
try {
options.stringify = require(tools.appName + '.' + adapter + '/lib/convert.js').stringify;
} catch (e) {
}
_getAllFilesInDir(objects, id, name, options, function (err, files) {
var count = 0;
if (files) {
JSZip = JSZip || require('jszip');
var zip = new JSZip();
var additional = [];
for (var f = 0; f < files.length; f++) {
count++;
_addFile(objects, id, files[f], options, zip, additional, function (err, additional) {
if (!--count) {
if (additional && additional.length) {
for (var ff = 0; ff < additional.length; ff++) {
if (!additional[ff] || typeof additional[ff] !== 'string') continue;
count++;
if (additional[ff][0] === '/') additional[ff] = additional[ff].substring(1);
var parts = additional[ff].split('/');
var adapter = parts.shift();
_addFile(objects, adapter, parts.join('/'), options, zip, null, function (err) {
if (!--count) {
zip.generateAsync({type: 'base64'})
.then(function (base64) {
callback(err, base64);
}, function (err) {
callback(err);
});
zip = null;
}
});
}
if (!count) {
zip.generateAsync({type: 'base64'})
.then(function (base64) {
callback(err, base64);
}, function (err) {
callback(err);
});
zip = null;
}
} else {
zip.generateAsync({type: 'base64'})
.then(function (base64) {
callback(err, base64);
}, function (err) {
callback(err);
});
zip = null;
}
}
});
}
}
if (!count) {
callback(err, null);
}
});
}
function _checkDir(objects, id, root, parts, options, callback) {
if (!parts || !parts.length) {
callback();
return;
}
root += '/' + parts.shift();
objects.readDir(id, root, options, function (err, files) {
if (err === 'Not exists') {
objects.mkdir(id, root, options, function (err) {
_checkDir(objects, id, root, parts, options, callback);
});
} else {
_checkDir(objects, id, root, parts, options, callback);
}
});
}
function _writeOneFile(objects, zip, id, name, filename, options, callback) {
zip.files[filename].async('nodebuffer').then(function (data) {
var _err;
if (options.parse) {
try {
data = options.parse(name, filename, data, options ? options.settings : null);
} catch (e) {
_err = e;
}
}
var fName = name + filename;
var parts = fName.split('/');
parts.pop();
_checkDir(objects, id, '', parts, options, function () {
objects.writeFile(id, name + filename, data, options, function (err) {
callback(_err || err);
});
});
}, function (err) {
callback(err);
});
}
function writeDirAsZip(objects, id, name, data, options, callback) {
JSZip = JSZip || require('jszip');
var zip = new JSZip();
options = options || {};
var adapter = id;
if (adapter.indexOf('.') !== -1) {
adapter = id.split('.')[0];
}
// try to load processor of adapter
try {
options.parse = require(tools.appName + '.' + adapter + '/lib/convert.js').parse;
} catch (e) {
}
try {
zip.loadAsync(data).then(function () {
var count = 0;
var error = [];
if (name[name.length - 1] !== '/') name += '/';
for (var filename in zip.files) {
if (!filename || filename[filename.length - 1] === '/') continue;
count++;
try {
_writeOneFile(objects, zip, id, name, filename, options, function (err) {
if (err) {
error.push('Cannot write file "' + filename + '":' + err.toString());
}
if (!--count && callback) {
callback(error.length ? error.join(', ') : null);
callback = null;
}
});
} catch (error) {
if (callback) {
callback(error.toString());
callback = null;
}
}
}
}, function (error) {
if (callback) {
callback(error.toString());
callback = null;
}
});
} catch (error) {
if (callback) {
callback(error.toString());
callback = null;
}
}
}
// pack all files as zip and send it back
function readObjectsAsZip(objects, rootId, adapter, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
options = options || {};
if (adapter) {
// try to load processor of adapter
try {
options.stringify = require(tools.appName + '.' + adapter + '/lib/convert.js').stringify;
} catch (e) {
}
}
objects.getConfigKeys(rootId + '.*', options, function (err, keys) {
objects.getObjects(keys, options, function(err, objs) {
JSZip = JSZip || require('jszip');
var zip = new JSZip();
for (var f = 0; f < objs.length; f++) {
var data = {id: keys[f], data: objs[f]};
if (options.stringify) {
try {
data = options.stringify(data, options ? options.settings : null);
} catch (e) {
data.id = keys[f].replace(/\./g, '/').substring(rootId.length + 1) + '.json';
}
} else {
data.id = keys[f].replace(/\./g, '/').substring(rootId.length + 1) + '.json';
}
if (typeof data.data === 'object') data.data = JSON.stringify(data.data, null, 2);
zip.file(data.id, data.data);
}
zip.generateAsync({type: 'base64'})
.then(function (base64) {
callback(err, base64);
}, function (err) {
callback(err);
});
});
});
}
function _writeOneObject(objects, zip, rootId, filename, options, callback) {
zip.files[filename].async('nodebuffer').then(function (data) {
data = {data: data.toString(), id: filename};
if (options.parse){
try {
data = options.parse(data, options ? options.settings : null);
} catch (e) {
callback('Cannot custom parse "' + data.id + '": ' + e);
return;
}
} else {
data.id = (rootId ? (rootId + '.') : '') + data.id.replace(/\//g, '.').replace(/\.json$/, '');
}
if (typeof data.data !== 'object') {
try {
data.data = JSON.parse(data.data);
} catch (e) {
callback('Cannot parse "' + data.id + '": ' + e);
return;
}
}
if (data && data.id && data.data) {
options.ts = new Date().getTime();
options.from = 'system.host.' + tools.getHostName() + '.cli';
objects.setObject(data.id, data.data, options, function (err) {
callback(err);
});
} else {
if (data && data.error) {
callback(data.error);
} else {
callback();
}
}
}, function (err) {
callback('Cannot parse unzip: ' + err);
});
}
function writeObjectsAsZip(objects, rootId, adapter, data, options, callback) {
JSZip = JSZip || require('jszip');
options = options || {};
if (adapter) {
// try to load processor of adapter
try {
options.parse = require(tools.appName + '.' + adapter + '/lib/convert.js').parse;
} catch (e) {
}
}
var zip = new JSZip();
try {
zip.loadAsync(data).then(function () {
var count = 0;
var error = [];
for (var filename in zip.files) {
if (filename[filename.length - 1] === '/') continue;
count++;
_writeOneObject(objects, zip, rootId, filename, options, function (err) {
if (err) error.push(err.toString());
if (!--count && callback) {
callback(error.length ? error.join(', ') : null);
callback = null;
}
});
}
}, function (error) {
if (callback) {
callback(error.toString());
callback = null;
}
});
} catch (error) {
if (callback) {
callback(error.toString());
callback = null;
}
}
}
module.exports.readDirAsZip = readDirAsZip;
module.exports.writeDirAsZip = writeDirAsZip;
module.exports.readObjectsAsZip = readObjectsAsZip;
module.exports.writeObjectsAsZip = writeObjectsAsZip;