Expressjs: ENOENT when uploading image - javascript

I have written some middleware for uploading an avatar, like this:
var gm = require('gm'),
mkdirp = require('mkdirp'),
fs = require('fs');
uploadAvatar = function(req, res, next) {
var img, path, user;
if (req.files.avatar_image) {
user = req.user;
img = req.files.avatar_image;
path = __dirname + "/../../public/avatar/" + (user.name.parameterize()) + ".png";
mkdirp.sync(__dirname + "/../../public/avatar/");
fs.createReadStream(img.path).pipe(fs.createWriteStream(path));
gm(path).resize(250, 250).autoOrient().quality(90).write(path, function(err) {
if (err != null) {
req.flash('error', err);
} else {
user.avatar = "/avatar/" + (user.name.parameterize()) + ".png";
user.save(function(err) {
if (err != null) {
req.flash('error', err);
}
next();
});
}
});
} else {
next();
}
};
// Usage
app.post('/upload', ensureAuthenticated, uploadAvatar, handleUpload);
When I now try to upload an image, node crashed with the incredibly helpful error message:
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, open '/tmp/1126846a248af5c584770b07de649f9b.png'
I have tried copying the file before using gm on it, too. I suspect that express deletes the file before I can even touch it, as a "security".
Can anyone help me here?
EDIT: Full source

First of all copy temp file to your avatar directory, and second make sure that you have permissions on avatar as well as temp directory and files.
As well piping read to write stream is not sync operation, and you will try to pipe straight after initialising read handle, that might lead to some problems.
You need to add events and wait till file get copied:
var complete = function(err) {
if (!err) {
// process your gm
} else {
console.log(err);
}
}
var read = fs.createReadStream(sourcePath);
read.on('error', function(err) {
complete(err);
});
var write = fs.createWriteStream(targetPath);
write.on('error', function(err) {
complete(err);
});
write.on('close', function() {
complete();
});
read.pipe(write);

Related

Nodejs Not able to create directory

I want to post an image to server.But before that I want to make sure that directory is create, before placing an image to a correct folder.The folder that I want to create is year/month/day/[image]. I am able to generate the folder on my local PC, but when I want to apply on the server, an error message is displayed and the folder is not created.I don't know what mistake that I have made, I hope someone can help me solve this problem.
Thank you in advance.
PWD
ERROR
return binding.mkdir(pathModule._makeLong(path), Error: ENOENT: no
such file or directory, mkdir
'/home/eis/development/eis-api-dev/picture/2020/06/01/'
CODE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
///output: home/eis/development/eis-api-dev/picture/2020/06/01/
const dir = path.join(__dirname,_const.IMAGE_FILE_PATH+_const.generateImagePath(null,null,null));
console.log("path:"+dir);
fs.exists(dir,exists =>{
if(!exists){
//mkdirp.sync(dir);
return fs.mkdirSync(dir,{recursive: true},error => cb(error,dir));
}
return cb(null,dir)
});
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
try to create using mkdirp
if (!fs.existsSync(directoryPath)){
mkdirp(directoryPath, function (err) {
if (err) {
console.log("Error Creating Directory "+directoryPath);
}
else {
console.log("Creating Directory "+directoryPath);
}
}
I just have to upgraded latest nodejs version and its worked.
To create a directory asynchronously
const fs = require('fs');
const path = 'newfolder/xyz/';
fs.exists(path, exists => {
if (exists) {
console.log('The directory exists...!!');
}
else {
fs.mkdir(path, { recursive: true }, (error) => {
console.log(error);
if (error)
// print or display your error
else {
return path;
}
});
}
});

Node.js + Express not writing to file using FS

I have a file that I am trying to write to from a post. Currently, the FS does not error nor does it write to file. However, when taking the same code from the deployed build and running it locally, it works. I even kept the file path consistent since it was throwing no permissions error at first. I ensured this file wrote to the same directory so each Filewrite Stream process would look at the same directory and file.
Local build:
var fs = require('fs');
const path = require('path');
var user_name = 'Password';
var password = 'test';
var errSTR = ""
fs.writeFile('C:\\hi.txt', 'Content to write', { flag: 'w' }, function(err) {
if (err)
return console.error(err);
fs.readFile('C:\\hi.txt', 'utf-8', function (err, data) {
if (err)
return console.error(err);
console.log(data);
});
});
Deployed Build:
app.route('/test')
.get(function(req, res) {
res.send('GET test');
})
.post(function(req, res) { // Start Post
var boolTry = false;
try {
boolTry = true;
var bool = false
var user_name = "Password"//req.body.user;
var password = "test"//req.body.password;
var errSTR = ""
fs.writeFile('C:\\hi.txt', user_name + password, { flag: 'w' }, function(err) {
if (err)
return console.error(err);
fs.readFile('C:\\hi.txt', 'utf-8', function (err, data) {
if (err)
return console.error(err);
res.send(500 + err);
console.log(data);
});
})
} catch (error) {
bool = true
errSTR = error
}
res.send('POST test' + " " + boolTry + " " + bool + " " + errSTR + ";")
})//END POST
.put(function(req, res) {
res.send('PUT test');
});
The local build will properly write to the file, while the dev build appears to do nothing. It should be noted by booleans were being used to understand how the file writer works but here is the server response from build: successful response POST test true false ;
Using:
IISNODE for iis: 7.x
Express: 4.16.2
node.js: v8.9.4
cors: 2.8.4
body-parser: 1.17.2
Sidenote: If you are confused by the writing portion of code, the intention was to write, check error then read, check error for assurance.
Update
Reoccurring error based on certain filewrite methods Error: EPERM: operation not permitted, open. Yes, all permissions for the directory are enabled along with ensuring read and write are checked.

pipe works on localhost but not on remote nodejs

I'm trying to use ytdl-core module in order to download youtube audio to my local disk (some path on my computer).
I created an API to which I can call with the requested youtube url and the destination folder in which I want the file to be saved.
app.get('/api/downloadYoutubeVideo', function (req, res) {
var videoUrl = req.query.videoUrl;
var destDir = req.query.destDir;
ytdl.getInfo(videoUrl, function(err, info){
var videoName = info.title.replace('|','').toString('ascii');
var stream = ytdl(videoUrl, { filter: 'audioonly'})
.pipe(fs.createWriteStream(destDir + '\\' + videoName + '.mp3'));
stream.on('finish', function() {
res.writeHead(204);
res.end();
});
});
});
The problem is that when I call the api on my localhost (example: localhost:11245/api/downloadYoutubeVideo?videoUrl=https://www.youtube.com/watch?v=E5kJDWQSBUk&destDir=C:\test)
it works and the file indeed downloads to "C:\test".
But when I call to the api on my remote (example: http://sometest.cloudno.de/api/downloadYoutubeVideo?videoUrl=https://www.youtube.com/watch?v=02BAlrAkuCE&destDir=C:\test)
it doesnt create the file in the directory...
I have searched the answer but haven't found one...
Does C:\test already exist on your remote? If not you can't use fs.createWriteStream() until the directory has been created, it will not create the directory for you implicitly. Since you're not listening for an 'error' event, you wouldn't even know that was the problem since you're not capturing it.
The below code sample will check for the existence of destDir and if it doesn't exist will create it before proceeding.
const fs = require('fs');
const sep = require('path').sep;
function checkAndMakeDir(dir, cb) {
fs.access(dir, (err) => {
if (err)
fs.mkdir(dir, (err) => {
if (err)
return cb(err);
return cb();
});
else
return cb();
});
}
app.get('/api/downloadYoutubeVideo', function (req, res) {
let videoUrl = req.query.videoUrl;
let destDir = req.query.destDir;
checkAndMakeDir(destDir, (err) => {
if (err) {
res.writeHead(500);
return res.end();
}
ytdl.getInfo(videoUrl, function (err, info) {
let videoName = info.title.replace('|', '').toString('ascii');
let saveStream = fs.createWriteStream(`${destDir}${sep}${videoName}.mp3`);
saveStream.once('error', (err) => {
console.log(err);
res.writeHead(500);
return res.end();
});
saveStream.once('finish', () => {
res.writeHead(204);
return res.end();
});
ytdl(videoUrl, {filter: 'audioonly'})
.once('error', (err) => {
console.log('Read Stream Error', err);
res.writeHead(500);
return res.end();
})
.pipe(saveStream);
});
});
});

Moved route from app.js to route.js and app no longer works

In my app.js file I had the code below and it worked as intended. I need to clean up my code, so I moved it to it's own route at routes/random and it no longer works because I get an error that states: "http://localhost:1337/random/1/1/testing 404 (Not Found)" and I am not sure why. My original code was in my app.js file when it was working was:
app.get('/random/:room/:userId/:message', function(req, res) {
fs.appendFile(room.number.toString(), req.params.message, function(err) {
if (err) {
console.log('error writing messages to file');
};
fs.readFile('./' + room.number, 'utf-8', function(err, data) {
if (err) {
if (err.fileNotFound) {
return this.sendErrorMessage('can\'t find the file, you linked it incorrectly');
}
console.log('error reading message file');
};
if (req.params.userId == 1) {
messages.user1.push(data);
} else {
messages.user2.push(data);
};
console.log(messages);
res.send(data);
fs.unlink(req.params.room, function(err) {
});
});
});
});
the new code includes the following for app.js
var express = require('express');
var app = express();
var fs = require('fs');
var random = require('./routes/random');
app.use('/random/', random);
app.use(express.static('public'));
app.use(express.static('public/js'));
app.use(express.static('public/images'));
and after I moved it, the route code is:
var express = require ('express');
var fs = require ('fs');
var random = express.Router();
random.get('/random/:room/:userId/:message', function(req, res) {
fs.appendFile(room.number.toString(), req.params.message, function(err) {
if (err) {
console.log('error writing messages to file');
};
fs.readFile('./' + room.number, 'utf-8', function(err, data) {
if (err) {
if (err.fileNotFound) {
return this.sendErrorMessage('can\'t find the file, you linked it incorrectly');
}
console.log('error reading message file');
};
if (req.params.userId == 1) {
messages.user1.push(data);
} else {
messages.user2.push(data);
};
console.log(messages);
res.send(data);
fs.unlink(req.params.room, function(err) {
});
});
});
});
module.exports = random;
Can anyone explain what I have done wrong that won't allow it to find the file?
In your code you are defining a route called random\random... in random.js, delete first random there, because middleware(app.use..) will direct all routes with /random to your router instance.
Your router is handling a url that starts with /random, and you attach this to your app under the path /random/. Remove one or the other (preferebly, the one inside the router).
I was able to fix it. Both comments above are correct, but it still was throwing errors due to my variables being undefined. I figured it out though so I am closing this question. Thank you both

node.js & Express / body parser

I write server side application with express & node.js.
I have the next:
app.configure(function () {
app.use(express.bodyParser());
});
Everything works good, but:
As I understand, this method was deprecated.
The next method doesn't work well. It writes some random chars instead of writing the correct chars:
app.post('/randomWrite', function (req, res) {
var fileName = req.body.name;
var contentLength = parseInt(req.files.file._writeStream.bytesWritten);
var start = parseInt(req.body.chunk) * 102400;
var buffer = new Buffer(parseInt(req.files.file._writeStream.bytesWritten));
fs.open(req.files.file.path, 'r', function (status, fd) {
if (fd == null) {
console.log("Can't open the file with the fd");
return;
}
fileNameLocation = "./" + fileName;
fs.open(fileNameLocation, 'w+', function (err, fd1) {
fs.read(fd, buffer, 0, contentLength, start, function (err, bytesRead, buffer1) {
if (err)
console.log("ERROR: " + err);
fs.write(fd1, buffer1, 0, contentLength, start, function (err, bytesWrite, buffer) {
if (req.body.chunk == req.body.chunks - 1) {
fs.close(fd, function (err) {
})
fs.close(fd1, function (err) {
})
FileServer.prototype.returnResCodeWithId(res, 200, id);
} else {
fs.close(fd, function (err) {
})
fs.close(fd1, function (err) {
})
FileServer.prototype.returnResCode(res, 200);
}
})
})
})
})
Instead of writing in the correct offset, it seems that something get wrong and some text from the middleware (bodyParser) is written.
How can i change the express.bodyParser()? It will fix my problem with the writing?
You need to use the Body-parser middleware.
You can install it with
npm install body-parser
and include it with Express using
var bodyparser = require('body-parser');
app.use(bodyparser());
If you want file uploads too, then have a look at multer.

Categories

Resources