NodeJS download remote to local FTP - node.js

I'm trying to download a remote location on a FTP server to my local directory. I've been using the jsftp module (https://github.com/sergi/jsftp) for this, but I'm running into a problem.
Basically I'm trying to recursively download the whole remote location, including all the sub-folders etc. I've been trying to figure it out myself, but so far no luck.
so far I've been trying this:
var worker = {
ftp: null,
init: function() {
this.ftp = new JSFtp({
host: "localhost",
port: 21,
user: "username",
pass: "password"
});
this.ftp.auth("username", "password", function (result) {
if (typeof result !== "undefined") {
console.log("Something went wrong");
}
this.handleData();
}.bind(this));
},
handleData: function () {
recursive_get_files(this, "/");
}
};
function recursive_get_files(worker, dir) {
console.log("Getting directory: " + dir);
worker.ftp.ls(dir, function (err, res) {
res.forEach(function (file) {
if (file.type === 1) {
recursive_get_files(worker, dir + "/" + file.name);
} else {
worker.ftp.get(dir + "/" + file.name, "/downloads" + dir + "/" + file.name, function(err) {
if (err) {
console.log("Couldn't download file: " + file.name);
console.log(err);
}
}.bind(file.name));
}
});
});
}
The biggest problem, I think, is that all these get functions are getting called almost instantly after each other, and since the client is probably not allowed to call so many things, it will break.
I've seen a module named ftpsync (https://www.npmjs.com/package/ftpsync) do some remote syncing, from local to remote, but I need this the otherway around.
is anyone able to help me here? I've been stuck on this all day =/.

I was able to fix this with a friend of mine by doing the following:
function recursive_get_files(workerf, dir) {
total_pending++;
var worker = workerf;
var done = function() {
//probably callback here if needed
console.log("finished downloading ftp");
wrench.chmodSyncRecursive('downloads', 0777);
worker.respond(JSON.stringify({type: "success", message: "Finished"}));
};
var func_download = function() {
//Is the download queue empty?
if(download_queue.length === 0)
{
total_running--;
if(total_running === 0 && total_pending === 0)
{
done();
}
return;
}
//Get the next download in the queue
var download = download_queue[0];
download_queue.splice(0, 1);
//Get a free FTP connection
var curftp;
for(curftp = 0; curftp < total; curftp++) {
if (worker.ftp[curftp].used === false) {
worker.ftp[curftp].used = true;
break;
}
}
//Get the file
worker.ftp[curftp].ftp.get(download.dir + "/" + download.file.name, "downloads/" + worker.project + download.dir + "/" + download.file.name, function(file, err) {
worker.ftp[curftp].used = false;
if (err)
{
console.log("Couldn't download file with FTP(" + curftp + "): " + file);
console.log(err);
setTimeout(func_download, 0);
}
else
{
console.log("Downloaded file with FTP(" + curftp + "): " + file);
setTimeout(func_download, 0);
}
}.bind(null, download.file.name));
};
//Get a list of the current directory (Using the main connection)
worker.mainftp.ls(dir, function (err, res) {
res.forEach(function (file) {
if (file.type === 1)
{
mkdirp("downloads/" + worker.project + dir + "/" + file.name, function(err) {
if (err) console.log(err);
recursive_get_files(worker, dir + "/" + file.name);
});
}
else
{
download_queue.push({file: file, dir: dir});
if(total_running < total)
{
total_running++;
setTimeout(func_download, 0);
}
}
});
});
total_pending--;
if(total_running === 0 && total_pending === 0 && download_queue.length === 0)
{
done();
}
}
it uses wrench.js (for recursive chmod) and jsftp. Thanks for reading ^^

Related

Getting a 503 error with NodeJS and ExressJS

I get a 503 error using NodeJS. My function works in localhost but on my remote server I get a 503 error.
Functions :
function postEdit(request, response) {
var updatedParams = request.body.updatedParams,
blockName = request.params.blockname,
primaryColor, secondaryColor, variables, scssStr;
if (blockName === 'themeparam') {
primaryColor = updatedParams.primary_color;
secondaryColor = updatedParams.secondary_color;
variables = updatedParams.variables;
if (primaryColor || secondaryColor || variables) {
scssStr = fs.readFileSync('./public/sass/_functions.scss', 'utf8');
scssStr += fs.readFileSync('./public/sass/_settings.scss', 'utf8');
if (primaryColor) {
scssStr = scssStr.replace(/\$main-color:.+;/g, '$main-color: ' + primaryColor + ';');
}
if (secondaryColor) {
scssStr = scssStr.replace(/\$secondary-color:.+;/g, '$secondary-color: ' + secondaryColor + ';');
}
scssStr += fs.readFileSync('./public/sass/app.scss', 'utf8');
scssStr = scssStr.replace(/#import.+;/g, '');
if (variables) {
scssStr += variables;
}
fs.readdir('./public/sass/components', function(err, files) {
files.forEach(function(file) {
scssStr += fs.readFileSync('./public/sass/components/' + file, 'utf8');
});
fs.readdir('./public/sass/shortcodes', function(err, shortcodeFiles) {
shortcodeFiles.forEach(function(shortcodeFile) {
scssStr += fs.readFileSync('./public/sass/shortcodes/' + shortcodeFile, 'utf8');
});
fs.writeFileSync('./public/uploads/theme.scss', scssStr);
sass.render({
file: './public/uploads/theme.scss'
}, function(err, result) {
if (err) {
console.log(err);
}
fs.writeFileSync('./public/uploads/theme.css', result.css);
});
});
});
} else {
fs.stat('./public/uploads/theme.scss', function(err) {
if (err) {
console.log(err);
}
if (!err) {
fs.unlinkSync('./public/uploads/theme.scss');
fs.unlinkSync('./public/uploads/theme.css');
}
});
}
}
if (blockName === 'robotparam') {
fs.writeFileSync('./public/robots.txt', updatedParams.robot);
}
editJsonFile(request, response, './configs/options.json', function(options) {
_.forEach(updatedParams, function(value, name) {
var blockParam = _.find(options.blocks, { name: blockName }),
param = _.find(blockParam.params, { name: name });
param.value = value;
});
}, OptionController.baseUrl + '/edit/block/' + blockName);
}
function editJsonFile(request, response, jsonFile, updater, redirectUrl) {
fs.readFile(jsonFile, 'utf8', function(err, data) {
if (err) {
throw err;
}
var options = JSON.parse(data);
updater(options);
fs.writeFile(jsonFile, JSON.stringify(options, null, 4), function(err) {
if (err) {
throw err;
}
request.flash('success', 'Done !');
response.redirect(redirectUrl);
});
});
}
Error 503 :
Service Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
Apache/2.4.7 (Ubuntu) Server at ****** Port 443
Is there any solution to get the error message to find the issue ?

Node-SerialPort Issue w/ Multiple Writes

When I pass an array with 1 element everything works great, when I pass one with two (max for our use case) I get the following error:
There's no write queue for that file descriptor (after write)!
Here is my code:
exports.triggerPhysical = function(state, alerts) {
console.dir("IN PHYSICAL");
console.dir(alerts);
SerialPort.list(function(err, ports) {
var port = {};
for(var i = 0; i < ports.length; i++) {
try {
if(typeof ports[i].manufacturer != 'undefined' && ports[i].manufacturer.includes("Numato")) {
port = ports[i];
}
} catch(err) {
console.dir(err);
}
}
var numato = new SerialPort(port.comName, {baudrate : 19200}, function(err) {
if(err) {
return console.dir(err);
}
console.dir('calling write');
for(var j = 0; j < alerts.length; j++) {
numato.write('relay ' + state + ' ' + alerts[j].index + '\r', function(err) {
if(err) {
console.dir('error writing');
console.dir(err);
}
console.dir('serial message written');
});
}
numato.close();
return true;
});
});
}
First write works great, second one fails. I am guessing there is an obvious solution but I am not finding it. Any insight would be much appreciated.
I ended up doing two things to resolve this issue. First I upgraded to version 5.x of the node-serialport library.
Second, I changed my code to the following:
exports.triggerPhysical = function(state, alerts) {
var port = new SerialPort('/dev/ttyACM0');
port.on("open", function() {
alerts.forEach(function(alert, idx) {
str = 'relay ' + state + ' ' + alert.index + '\r';
port.write(str, function(err, results) {
if(err) {
console.dir("err writing");
console.dir(err);
} else {
console.dir(results);
}
});
});
})
port.drain(writeDone);
function writeDone() {
console.dir("In writeDone");
port.close();
}
}
I am now able to do consecutive writes without causing any errors and the port doesn't end up in a weird locked state.

local variable is not changing

I'm using node.js for converting text files to CSV. It works for one file, but when i try process more files fileDestination variable doesn't change. Why? Input files like this: r10_1C_BP1-11_e41-81_10_5X1x9_05_train2.res
I got following console output:
./1_train.csv has been written successufully! r10_1C_BP1-11_e41-81_10_5X1x9_05_train2.res
./1_train.csv has been written successufully! r10_1C_BP1-11_e41-81_1_5X1x9_05_train2.res
/*
* lee archivos *.dat y los convierte *.csv
*/
const fs = require('fs');
const inputDir = './';
const outputDir = './';
function readFiles(inputDir, onError) {
fs.readdir(inputDir, function(err, filenames) {
if (err) {
onError(err);
return;
}
filenames.forEach(function(inputFile) {
// first we arre looking for "right" file name
if (inputFile.search(/res/) != -1) {
console.log('Starting processing ' + inputFile);
convert2csv(inputFile, function(error) {
throw err;
});
}
});
});
}
function convert2csv(filename, onError) {
arrayFromFilename = filename.split('_');
epoca = arrayFromFilename[4];
trainORval = arrayFromFilename[7].replace('2.res', '');
console.log("from convert " + filename + " " + epoca);
fs.readFile(inputDir + filename, 'utf-8', function(err, content) {
if (err) {
onError(err);
return;
}
content = content.replace(/^[^0].*\n/mg, '');
arr = content.split('\n');
pares = arr.filter(function(d, i) {
return i % 2 == 1;
});
content = pares.join('\n');
content = content.replace(/(^[\d.]*) ([\d.]*)/gm, '$1,$2');
fileDestination = outputDir + epoca + '_' + trainORval + '.csv';
console.log("filedestination :" + fileDestination);
fs.writeFile(fileDestination, 'y,x\n', function(err) {
if (err) {
return console.error(err);
}
fs.appendFile(fileDestination, content, function(err) {
if (err) {
return console.error(err);
}
console.log(fileDestination + " has been written successufully!", filename);
});
});
});
}

node.js move bunch of files

i have made a form for file upload and i have set the multiple option, so im trying to upload a bunch of files and then move them according to the album name that the client have set,
here is what iv done:
if (req.body && req.body.album){
var album_name = req.body.album;
}
else{
//need to change to time instead of random album
var album_name = 'unknown_album-' + (parseInt(Math.random() * 5) + 1);
}
//File name
var file_name = null;
switch(req.files.img_file.type){
case 'image/png':
file_name = new Date().getTime() + '.png';
break;
case 'image/jpeg':
file_name = new Date().getTime() + '.jpeg';
break;
default:
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ לא תקין'
});
break;
}
mkdirp('./public/img/albums/' + album_name, function (err) {
if (err)
console.error(err);
else
{
_.each(req.files.img_file,function(val,index){
console.log(val.path + " " + index);
//gives the file path so i can read it
fs.readFile(val.path, function (err, data) {
if (err){
console.log("fs " + err);
}
//so until here everything works fine, the files are uploaded to the "/uploads" directory, now im trying to move them to the correct album, the destiation is : public/img/albums/:album_name/:all_images here
mv(val.path, './public/img/albums/' + album_name + '/' + val.path, function(err) {
if (err){
console.log("mv " + err);
}
else{
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ עלה בהצלחה'
});
res.redirect('/admin');
}
});
});
});
}
});
the mv module throws an error rename "c:/work/xxx/xx/uploads/val.path.png
Its a file-access error. You X out some of the file name, but look at how that NPM module handles file, and ensure you are naming the files and paths properly. Then it should work out fine.
i have used read and write stream and deleted the "mv" module
if (req.body && req.body.album){
var album_name = req.body.album;
}
else{
//need to change to time instead of random album
var album_name = 'unknown_album-' + (parseInt(Math.random() * 5) + 1);
}
//File name
if (req.files.img_file.length > 1)
{
var Counter = 0;
_.each(req.files.img_file,function(val,index){
var file_name = null;
switch(val.type){
case 'image/png':
file_name = new Date().getTime() + '.png';
break;
case 'image/jpeg':
file_name = new Date().getTime() + '.jpeg';
break;
}
mkdirp('./public/img/albums/' + album_name, function (err) {
if (err)
console.error(err);
var source = fs.createReadStream(val.path);
var dest = fs.createWriteStream('./public/img/albums/' + album_name + '/' + val.name);
source.pipe(dest);
source.on('end', function() {
console.log('end...');
Counter++;
console.log(Counter);
console.log(req.files.img_file.length);
if (Counter == req.files.img_file.length){
res.redirect('/admin');
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ עלה בהצלחה',
albums: albums
}); //eo res render
}
});
source.on('error', function(err) { console.log('error'); });
});// eo mkdir
}); // eo _each
}

trouble using fs module to locate file

Here is my code:
connection.query("SELECT * FROM images", function(err, rows, fields) {
if (err) {
console.log("Error: ");
console.log(err);
}
else {
console.log("rows: ");
console.log(rows);
for (var i = 0; i < rows.length; i++) {
var thisRow = rows[i];
var thisImageName = thisRow["imagename"];
var newDir = __dirname.split(path.sep).join("/");
var thisImagePath = newDir + "/public/uploads/" + thisImageName + ".jpg";
console.log(thisImagePath);
fs.exists(thisImagePath, function(exists) {
if (exists) {
console.log("true");
res.end();
}
else {
console.log(thisImageName + " does not exist."); res.end();
//Always returns false
}
});
}
}
});
HOWEVER,
In the console:
fs.exists(/* imagepath */, function(exists){console.log(exists)}) //returns true
As you can see I'm using the node-mysql library to return the file names of my images. I concatenate them using the __dirname global and then I reverse the slashes in the directory string to use in the .exists() call. When I use the fs module to check if the image file exists, it returns false.
HOWEVER, if I use fs.exists() with the same path in the console, it returns true. Does anyone know what's going on here?

Resources