Move file in Nodejs if file exists otherwise create file - node.js

I am trying to move a file from a location abc to location xyz if the file already exists in location xyz delete it then save the new one.
Here is my code
const promises = {
deleteFile: path => {
return new Promise((resolve, reject) => {
const fs = require('fs');
fs.stat(path, (err, stat) => {
if (err === null) {
fs.unlink(path, err => {
if (err) { return reject(err) }
resolve();
})
} else if(err.code == 'ENOENT') {
console.log('File does not exist');
resolve();
} else {
reject(err);
}
});
});
},
copyFile: (from, to) => {
return new Promise((resolve, reject)=> {
copyFile(from, to, (err) => {
if (err) { return reject(err); }
console.log(`Finished writing file ${to}`);
resolve();
})
})
}
}
const copyFile = (from, to, overallCb) => {
const fs = require('fs');
const rs = fs.createReadStream(from)
const ws = fs.createWriteStream(to)
let cbCalled = false;
function done (err) {
overallCb(err);
cbCalled = true;
}
rs.on('error', (err) => {
done(err);
})
ws.on('error', (err) => {
done(err);
})
rs.pipe(ws);
}
;
const OUTPUT_PATH = `./js/libs/`
, _NODE_MODULES = './node_modules/'
, filePath = `${_NODE_MODULES}somePathToAFile`
;
promises.deleteFile(`${OUTPUT_PATH}someFile.min.js`)
.then(promises.copyFile(filePath, `${OUTPUT_PATH}someFile.min.js`))
.then(words => {
console.log('**** done doing things ****');
})
.catch(error => { console.log(`ERROR`, error); })
If the file exists it just simply deletes the file and does nothing else.
If the file DOES NOT exist everything works fine.
Any idea on what im doing wrong?

I had some promise errors in my code... For future me here is the working version of the above code
'use strict';
const promises = {
deleteFile: path => {
return new Promise((resolve, reject) => {
const fs = require('fs');
fs.stat(path, (err, stat) => {
if (err === null) {
fs.unlink(path, err => {
if (err) { return reject(err) }
resolve(`Removing document at ${path}`);
})
} else if(err.code === 'ENOENT') {
resolve('File does not exist');
} else {
reject(err);
}
});
});
},
copyFile: (from, to) => {
return new Promise((resolve, reject) => {
copyFile(from, to, (err) => {
if (err) { return reject(err); }
resolve(`Finished writing file ${to}`);
})
})
}
}
const copyFile = (from, to, overallCb) => {
const fs = require('fs');
const rs = fs.createReadStream(from)
const ws = fs.createWriteStream(to)
let cbCalled = false;
function done (err) {
overallCb(err);
cbCalled = true;
}
rs.on('error', done)
ws.on('error', done)
.on('close', done)
rs.pipe(ws);
}
;
const OUTPUT_PATH = './js/libs/'
, _NODE_MODULES = './node_modules/'
, filePath = `${_NODE_MODULES}somePathToAFile`
;
promises.deleteFile(`${OUTPUT_PATH}someFile.min.js`)
.then(msg => {
console.log(msg)
return promises.copyFile(filePath, `${OUTPUT_PATH}someFile.js`)
})
.then(msg => {
console.log(msg)
})
.catch(err => { // Do errory things}

Related

function, that returns Promise

I have a task with a promise and I don't understand how to do it.please help
1.Imports function "func1" from file "script1.js";
const func1 = a => {
switch (a) {
case 'a':
return new Promise((resolve) => {
setTimeout(() => {
resolve('result1');
}, 100);
});
case 'b':
return new Promise((resolve) => {
setTimeout(() => {
resolve('result2');
}, 100);
});
default:
return new Promise((resolve) => {
setTimeout(() => {
resolve('result3');
}, 100);
});
};
};
module.exports = func1;
Reads a string from the "input.txt";
input a
Calls "func1" with an argument equal to the string;
Waits until the received Promise has state: "fulfilled" and then outputs the result to the file "output.txt".
this is how i try to solve but nothing works:
const fs = require('fs')
const func1 =require ("./script1 (1)")
fs.readFile('./input.txt', 'utf8' , (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
async function one (data) {
try {
const result = await Promise(func1);
console.log(result);
} catch (err) {
console.log(err)
}}
fs.writeFile("output.txt",one().toString(), function(err)
{
if (err)
{
return console.error(err);
}
})
})
the result must be "result1"
To call a Promise you can use async await and try catch blocks. Once you have the asynchronous result value, you can call fs.writeFile(). Try this:
func1.js:
const func1 = a => {
switch (a) {
case 'a': return new Promise((resolve) => {
setTimeout(() => { resolve('result1'); }, 100);
});
case 'b': return new Promise((resolve) => {
setTimeout(() => { resolve('result2'); }, 100);
});
default: return new Promise((resolve) => {
setTimeout(() => { resolve('result3'); }, 100);
});
};
};
module.exports = func1;
index.js:
const fs = require('fs');
const func1 = require("./demo2.js")
fs.readFile('./input.txt', 'utf8' , async (err, data) => {
if (err) {
console.error(err);
return;
}
//console.log(data)
try {
const result = await func1(data);
console.log(result);
fs.writeFile("output.txt", result, function(err) {
if (err){
return console.error(err);
}
});
} catch (err) {
console.log(err)
}
});
the async/await way is to change const result = await Promise(func1); to const result = await func1(data); you can also use then like this const result = func1(data).then(res => res);
and a better func1 would be
const func1 = a => {
return new Promise((resolve) => {
setTimeout(() => {
switch(a) { // handle cases };
});
});
};
module.exports = func1;
const func1 = a => {
return new Promise((resolve) => {
switch (a) {
case 'a':
setTimeout(() => {
resolve('result1');
}, 100);
case 'b':
setTimeout(() => {
resolve('result2');
}, 100);
default:
setTimeout(() => {
resolve('result3');
}, 100);
};
})
};
module.exports = func1;
const fs = require('fs')
const func1 =require ("./script1 (1)")
fs.readFile("./input.txt", "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
async function one(data) {
try {
func1(data).then(result => {
console.log(result)
})
} catch (err) {
console.log(err);
}
}
fs.writeFile("output.txt", one().toString(), function (err) {
if (err) {
return console.error(err);
}
});
});

Transaction Global in Node-Firebird

I'm using "node-firebird" in my Firebird 2.5 project and I would like to use a single transaction for multiple inserts or update in some batches, but I couldn't use a global transaction. Could someone help me with this?
This is the single form in the official example:
Firebird.attach(options, function(err, db) {
if (err)
throw err;
// db = DATABASE
db.transaction(Firebird.ISOLATION_READ_COMMITED, function(err, transaction) {
transaction.query('INSERT INTO users VALUE(?,?)', [1, 'Janko'], function(err, result) {
if (err) {
transaction.rollback();
return;
}
transaction.commit(function(err) {
if (err)
transaction.rollback();
else
db.detach();
});
});
});
});
I trying this
const NewTransaction=()=>{
return new Promise((resolve, reject) => {
firebirdPool.get((err, db) => {
if (err) {
reject(err);
return;
}
DBGlobal=db;
DBGlobal.transaction(Firebird.ISOLATION_READ_COMMITED,
function(err, transaction) {
//here i trying save the transaction
TransactionGlobal=transaction;
if (err) {
reject(err);
return;
}
resolve(TransactionGlobal)
});
});//firebirdpool
});//promisse
}//function
const CommitTransaction=()=>{
return new Promise((resolve, reject) => {
TransactionGlobal.commit(function(err) {
if (err){
transaction.rollback();
reject(err);
return;
}
else {
DBGlobal.detach();
resolve(true);
}
});//transaction
});//promisse
}
const RollbackTransaction=()=>{
return new Promise((resolve, reject) => {
try{
TransactionGlobal.rollback();
resolve(true);
}
catch(err){
reject(err)
}
});//promisse
}
//usado com commit
const QueryExecTransaction = (sql,arrayparams=[]) => {
return new Promise((resolve, reject) => {
TransactionGlobal.query(sql,arrayparams,function(err, result) {
if (err) {
console.log('erro na execução da query');
TransactionGlobal.rollback();
reject(err);
return;
}
resolve(result);
return;
});//query
});//promisse
}
I run with this test
async function test(){
await NewTransaction();
console.log('Transacao Global',TransactionGlobal);
QueryExecTransaction(`insert into tabparametros(codigo,nome,valor) values (0,'teste1','')`);
CommitTransaction();
}
test();
But i received this error:
(node:9232) UnhandledPromiseRejectionWarning: Error: invalid transaction handle (expecting explicit transaction start)
I managed to solve, the alteration was in "commitretaining" and others small alters
below the code
//variaveis de "ambiente" salvas na raiz do projeto
//.env e .env.testing
require('dotenv').config({
path: (process.env.NODE_ENV === "test")||(process.env.NODE_ENV === "development") ? ".env.testing" : ".env"
})
var Firebird = require('node-firebird');
var fs = require('fs');
var options = {};
options.host = process.env.DB_HOST;
options.port = process.env.DB_PORT;
options.database = process.env.DB_DATABASE;
options.user = process.env.DB_USER;
options.password = process.env.DB_PASSWORD;
options.lowercase_keys = false; // set to true to lowercase keys
options.role = null; // default
options.pageSize = 4096; // default when creating database
//console.log(options);
//Conexao
// 5 = the number is count of opened sockets
var firebirdPool = Firebird.pool(5, options);
const NewTransaction=()=>{
return new Promise((resolve, reject) => {
firebirdPool.get((err, db) => {
if (err) {
reject(err);
return;
}
//aqui eu salvo o DB retornando
//DBGlobal=db;
db.transaction(Firebird.ISOLATION_READ_COMMITED,
function(err, transaction) {
//aqui eu salvo a transacao retornada
//TransactionGlobal=transaction;
if (err) {
reject(err);
return;
}
resolve({transaction,db});
});
});//firebirdpool
});//promisse
}//function
const CommitTransaction=(transaction,db)=>{
return new Promise((resolve, reject) => {
transaction.commitRetaining(function(err) {
if (err){
transaction.rollback();
reject(err);
return;
}
else {
db.detach();
resolve(true);
}
});//transaction
});//promisse
}
const RollbackTransaction=(transaction,db)=>{
return new Promise((resolve, reject) => {
try{
transaction.rollback();
db.detach();
resolve(true);
}
catch(err){
reject(err)
}
});//promisse
}
//usado com commit
const QueryExecTransaction = (transaction,sql,arrayparams=[]) => {
return new Promise((resolve, reject) => {
transaction.query(sql,arrayparams,function(err, result) {
if (err) {
console.log('erro na execução da query');
transaction.rollback();
reject(err);
return;
}
resolve(result);
return;
});//query
});//promisse
}
async function testa(){
const {transaction,db}=await NewTransaction();
//console.log('Transacao Global',transaction);
let psql='';
try{
for (let i=1;i<101;i++){
psql=`insert into tabparametros(codigo,nome,valor) values (0,'teste${i}-${new Date()}','')`
if (i==79){
//psql='forcando o erro';
}
await QueryExecTransaction(transaction,psql);
}
await CommitTransaction(transaction,db);
}
catch(e){
console.log('Erro no SQL');
console.log(e);
await RollbackTransaction(transaction,db);
}
console.log('Finalizado')
}
testa();

how to send response only after mv library on nodejs completes. Wrapping in promise doesn't work

I'm trying to setup an endpoint that takes a file through a multipart post request, and saves it into a specific directory using formidable and https://github.com/andrewrk/node-mv. And then upon completion of saving all of the files, I want to respond with a list of all of the files in that directory for rendering. the thing is the response seems to be sent before the directory listing is updated. I tried wrapping the mv operations into a promise and then responding in a then block to no avail. Any help would be much appreciated!
app.post("/api/v1/vendor/:id/menu", (req, res, next) => {
const id = req.params.id;
const form = formidable({ multiples: true, keepExtensions: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
if (!Array.isArray(files.image)) {
files = [files.image];
}
let filelist;
const proms = files.map((file) => {
const dst = `pics/${id}/${file.name}`;
new Promise((resolve, reject) => {
mv(file.path, dst, { mkdirp: true }, (err) => {
if (err) {
console.error("error: ", err.status);
reject(err);
}
console.log("done moving");
resolve();
});
});
});
Promise.all(proms).then(() => {
console.log('now reading dir...');
filelist = fs.readdirSync("pics/" + id);
res.send(filelist);
});
});
});
I think we're missing the return keywork before new Promise. You can check the proms variable if it contains the list of promises or not.
const proms = files.map((file) => {
const dst = `pics/${id}/${file.name}`;
new Promise((resolve, reject) => {
mv(file.path, dst, { mkdirp: true }, (err) => {
if (err) {
console.error("error: ", err.status);
reject(err);
}
console.log("done moving");
resolve();
});
});
});
For me, it should be :
const proms = files.map((file) => {
const dst = `pics/${id}/${file.name}`;
return new Promise((resolve, reject) => {
mv(file.path, dst, { mkdirp: true }, (err) => {
if (err) {
console.error("error: ", err.status);
reject(err);
}
console.log("done moving");
resolve();
});
});
});

storing file with Large Object Postgres with Nodejs

I have a simple HTML form with a file input. I need to save the file with Postgres Large Object but I'm having issues with the fileStream.pipe. It should be in a Promise itself like so:
return new Promise((resolve, reject) => {
stream.on('finish', resolve(oid));
stream.on('error', reject);
});
But it wouldn't work since it would result into a Promise in a Promise. The complete functions are:
function storeLargeObject(path) {
return new Promise((resolve, reject) => {
pgp.db.tx(tx => {
const man = new LargeObjectManager({pgPromise: tx});
return man.createAndWritableStreamAsync(bufferSize);
}).then(([oid, stream]) => {
const fileStream = createReadStream(path);
fileStream.pipe(stream);
stream.on('finish', resolve(oid));
stream.on('error', reject);
}).catch(err => {
console.log(err);
return err;
});
});
}
const addBinary = (req, res) => {
pgp.db.oneOrNone({
text: insertQuery,
values: values
}).then(f => {
let explFile = req.files.bin;
let uploadPath = __dirname + '/' + f.id;
if (!req.files || Object.keys(req.files).length === 0) {
res.status(400).send('No File was uploaded.');
return;
}
explFile.mv(uploadPath, async function (err) {
if (err)
return res.status(500).send(err);
let newOid = await storeLargeObject(uploadPath);
fs.unlink(uploadPath, err => console.log(err));
coupleIds(exp.id, newOid);
return res.status(200).send({
status: "success",
message: "File successfully uploaded!"
})
});
}).catch(err => {
return res.status(401).send({
status: 'error',
errorCode: 102,
message: 'Error! ' + err
});
});
}

Node.js tcp connection

How to send "End" message after resolving promise? Sometimes I can send 2 "end" messages out of 4, sometimes 3. Files from FTP are being downloaded and it's ok. The only thing that doesn't work is sending "end" message after downloading a file. Do you have any idea why this code doesn't work properly?
This code was updated:
const ftp = require("jsftp");
const fs = require("fs");
const net = require("net");
const mkdirp = require("mkdirp");
class ftpCredentials {
constructor(host) {
this.user = "xxx";
this.pass = "xxx";
this.host = host;
}
}
const downloadFromFTP = (credentials, file) => {
const client = new ftpCredentials(credentials.host);
const ftpClient = new ftp(client);
return new Promise((res, rej) => {
let buf = null;
ftpClient.get(file, (err, stream) => {
if (!err && typeof stream !== "undefined") {
// Events
stream.on("data", (data) => {
if (buf === null) buf = new Buffer(data);
else buf = Buffer.concat([buf, data]);
});
stream.on("close", (err) => {
if (err) rej("FILE_ERROR");
const actualPath = `${credentials.path}/${file}`;
fs.writeFile(actualPath, buf, "binary", (err) => {
if (err) rej(err);
ftpClient.raw("quit", (err, data) => {
if (err) rej(err)
res(file);
});
});
});
// Resume stream
stream.resume();
} else {
rej("STREAM_ERROR");
}
});
})
}
const handleSavingFile = (credentials, filesOnFTP) => {
mkdirp(credentials.path, () => {
fs.readdir(credentials.path, (err, fileNames) => {
if (err) return err;
const needToConnectToFTP = filesOnFTP.filter(name => fileNames.indexOf(name) !== -1).length === 0;
const socketForEndMsg = net.createConnection(18005, credentials.host, () => {
Promise.all(filesOnFTP.map((file) => {
return new Promise((resolve, reject) => {
// The problem is here:
const socketWrite = socketForEndMsg.write(`End|ftp://${credentials.host}/${file}`, "UTF16LE");
resolve(socketWrite);
// Events
socketForEndMsg.on("error", () => {
console.log("Problem with sending End message!");
reject();
});
});
})).then(() => {
socketForEndMsg.end();
}).catch((err) => {
console.log(err);
});
});
})
})
}
const getScheme = (credentials) => {
const socketForData = net.createConnection(18005, credentials.host, () => socketForData.write("Scheme", "UTF16LE"));
// Events
socketForData.on("close", () => console.log("TCP Connection closed"));
socketForData.on("error", err => console.log(err));
socketForData.on("data", (data) => {
socketForData.end();
const toUTF16Format = Buffer.from(data).toString("UTF16LE");
const arrayFromTCPMessage = toUTF16Format.split(/\||;/);
const filteredImages = arrayFromTCPMessage.filter(item => item.startsWith("scheme"))
const isOK = arrayFromTCPMessage[0] === "OK";
if (isOK) {
handleSavingFile(credentials, filteredImages);
}
})
}
module.exports = getScheme;
Error message: Error: This socket is closed
at Socket._writeGeneric (net.js:722:18)
at Socket._write (net.js:782:8)
at doWrite (_stream_writable.js:407:12)
at writeOrBuffer (_stream_writable.js:393:5)
at Socket.Writable.write (_stream_writable.js:290:11)
at Promise (xxx\getScheme.js:56:29)
at new Promise (<anonymous>)
at Promise.all.filesOnFTP.map (xxx\getScheme.js:54:18)
at Array.map (<anonymous>)
at Socket.net.createConnection (xxx\getScheme.js:52:32)
I see that, you like to listen to error event & that made you to use Promise to catch the error. But, the placement of the error event handler registration is wrong, as it is inside .map function call. So, error event will be registered number of times of filesOnFTP length.
I've moved that error handler to next line & using writable flag to see, if the socket is still writable before writing to it. I have also added few more event handlers, which will give you more information about the socket status(for debugging, you can remove them later).
const handleSavingFile = (credentials, filesOnFTP) => {
mkdirp(credentials.path, () => {
fs.readdir(credentials.path, (err, fileNames) => {
if (err) return err;
const needToConnectToFTP = filesOnFTP.filter(name => fileNames.indexOf(name) !== -1).length === 0;
const socketForEndMsg = net.createConnection(18005, credentials.host, () => {
for(let file of filesOnFTP) {
// Before write to socket, check if it is writable still!
if(socketForEndMsg.writable) {
socketForEndMsg.write(`End|ftp://${credentials.host}/${file}`, "UTF16LE");
}
else {
console.log('Socket is not writable! May be closed already?');
}
}
});
// This is the correct place for the error handler!
socketForEndMsg.on("error", (error) => {
console.log("Problem with sending End message!", error);
});
socketForEndMsg.on("close", () => {
console.log("Socket is fully closed!");
});
socketForEndMsg.on("end", () => {
console.log("The other end of the socket has sent FIN packet!");
});
});
});
}
Let me know if this works!
Thanks!
You can try to wait for connection event on socketForEndMsg and then start sending your data
const handleSavingFile = (credentials, filesOnFTP) => {
mkdirp(credentials.path, () => {
fs.readdir(credentials.path, (err, fileNames) => {
if (err) return err;
const needToConnectToFTP = filesOnFTP.filter(name => fileNames.indexOf(name) !== -1).length === 0;
const socketForEndMsg = net.createConnection(18005, credentials.host);
socketForEndMsg.on('connect', () => {
Promise.all(filesOnFTP.map((file) => {
return new Promise((resolve, reject) => {
// The problem is here:
const socketWrite = socketForEndMsg.write(`End|ftp://${credentials.host}/${file}`, "UTF16LE");
resolve(socketWrite);
// Events
socketForEndMsg.on("error", () => {
console.log("Problem with sending End message!");
reject();
});
});
})).then(() => {
socketForEndMsg.end();
}).catch((err) => {
console.log(err);
});
})
})
})
}

Categories

Resources