I am working on image upload via nodejs and multer module and this is the code im using:
app.post('/upload', upload.single('file'), function(req, res, next) {
var tmp_path = req.file.path,
target_path = __dirname + '/public/uploads/' + req.file.originalname,
src = fs.createReadStream(tmp_path),
dest = fs.createWriteStream(target_path);
src.pipe(dest);
fs.unlink(tmp_path); //deleting the tmp_path
src.on('end', function() {
res.json({
success: true,
file: '/uploads/' + req.file.originalname
});
});
src.on('error', function(err) {
console.log('err', err);
res.json({
success: false
});
});
});
The problem is that sometimes (it occures randomly) error callback is triggered, with this contents:
So it looks like additional slashes are added to the path which causes script not to find temp location and returns error, maybe someone encountered this problem and can help ;)
You can use the following code in order to get rid of this error...
try:- path.replace("\\","/");
This will definitely solve your problem.
Try running the unlink after success message is sent, pipe is asynchronous so might be executing after the delete.
src.on('end', function() {
res.json({
success: true,
file: '/uploads/' + req.file.originalname
});
fs.unlink(tmp_path)
});
Related
What is working
I am using the easy-ftp npm package with express-fileuploadto upload files onto an FTP server using node.js and react.js. The files are always uploaded successfully onto my local ftp into the path /test.
What's the issue
The issue is, that when files are saved in a temp directory before being uploaded onto the ftp server, they get renamed to the temp file name.
So a file called:
test.pdf
is renamed to:
tmp-1-1656368064718
on upload.
I have tried using the ftp.mv function according to the documentation everywhere within the app.post("/upload") route function. It simply just won't change the name. I don't understand what I am doing wrong.
I have been at it for days now, I really hope someone out there has an idea.
I am very grateful!
app.use(
fileUpload({
useTempFiles: true,
tempFileDir: "/tmp/",
preserveExtension: true,
})
);
app.post("/upload", (req, res) => {
console.log(req.files);
if (req.files === null) {
return res.status(400).json({ msg: "No file was uploaded" }); //error message if no file was uploaded
}
const file = req.files.file;
const tempFileName = file.tempFilePath.split("/").at(-1);
ftp.upload(file.tempFilePath, "/test", function (err) {
if (err) {
console.log(err);
return res.status(500).send(err);
} else {
console.log("finished:", res);
res.json({ fileName: file.name, filePath: `/test/${file.name}` });
}
ftp.mv(`/test/${tempFileName}`, "abc.pdf", function (error, newPath) {
console.log(error);
console.log(newPath);
});
ftp.close();
});
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`server started on port ${PORT}`));
How can I create a folder (if the folder does not exist yet) before the image will be uploaded? I always get error ENOENT.
When I try this code:
module.exports = function(router){
router.post('/result', directory.tmp, uploader.single, function(req,res){
//some data manipulation here
});
}
//directory.js
module.exports.tmp = function(req, res, next){
mkdirp('./tmp/' + moment().format('MM-DD-YY') + '/' + moment().format('HH'), function (err) {
if (err) console.error(err)
console.log("==================================");
console.log("tmp folder created");
console.log("==================================");
});
next();
};
Though I used directory.tmp first so it will create a folder if it is not existing, I think uploader.single is executed first that is why I got that error. After receiving the error, then that's the time my app created the folder. So in other words, the file uploaded was not saved. How to fix this so it will create the folder first, then upload the file. Btw, I am using mkdirp and multer.
I would suggest you to do the next(); inside the callback of mkdirp.
Because like you did, why it creates the folder it calls next and goes further and the folder is not yet created. This is why you should wait for folder creation first.
module.exports.tmp = function(req, res, next){
mkdirp('./tmp/' + moment().format('MM-DD-YY') + '/' + moment().format('HH'), function (err) {
if (err) console.error(err)
console.log("==================================");
console.log("tmp folder created");
console.log("==================================");
next();
});
};
I'm working on creating a simple file uploader on a node server with expressjs as the middleware. So far, the server side looks like:
app.post('/upload', function(req, res) {
console.log(req.files);
//Handle the file
fs.readFile(req.files.imageUploader.path, function(err, data) {
var newPath = __dirname;
console.log(newPath);
console.log(data);
fs.writeFile(newPath, data, function(err) {
console.log(err);
res.send("AOK");
});
});
});
Now, the log statement for __dirname is my source directory, as expected (C:\Development\GitHub\ExpressFileUpload), however an error is happening on the upload:
{ [Error: EISDIR, open 'C:\Development\GitHub\ExpressFileUpload']
errno: 28,
code: 'EISDIR',
path: 'C:\\Development\\GitHub\\ExpressFileUpload' }
I've tried changing the newPath to be / and ./ but no change, different errors, but still errors. Is it something to do with the double \\ in the path in the error? Am I missing something simple here? Thanks for the help, let me know if more info is needed.
The __dirname global object is a directory, not a file. Therefore, you can't open it for writing, which is what fs.writeFile() attempts to do in your script, hence the reason you are getting a EISDIR. Assuming you want the file to be written with the same name it was uploaded with, you can do this:
var file = req.files.imageUploader;
fs.readFile(file.path, function(err, data) {
var path = __dirname + '/' + file.name;
fs.writeFile(path, data, function(err) {
});
});
I need to get an user download his file and remove it after response get finished:
app.get('/download/:file', function (req, res) {
var filePath = '/files/' + req.param('file');
res.download(file);
fs.unlink(filePath);
});
In the code above fs.unlink could invoked early than res.download will get finished.
Use the callback in the download api:
res.download(filePath, req.param('file'), function(err){
//CHECK FOR ERROR
fs.unlink(filePath);
});
res.download(filePath, req.param('file'), function(err){
//CHECK FOR ERROR
fs.unlink(filePath);
});
am using express.js and uploadify to upload large file to node server, everything works fine except when more than one user login and try to upload file at same time, well it still works but it seems that the server can only upload one file at a time, so the user have to wait until the other user finish their uploading, this is so unacceptable.
here is server side code
exports.upload = function(req, res,next){
// console.log( req.body);
// console.log(req.files);
var tmp_path = req.files.product_video.path;
var target_path = 'F:/shopping/shop/' +req.body.shop_id+'/'+ req.files.product_video.name;
fs.rename(tmp_path, target_path, function(err) {
if (err) {
console.log(err)
}
else{
fs.unlink(tmp_path, function() {
if (err){
console.log(err)
}else{
exec("C:/ffmpeg/bin/ffmpeg -i shop/"+ req.body.shop_id+ '/' + req.files.product_video.name + " -ss 00:01:00.00 -r 1 -an -vframes 1 -s 250x150 -f mjpeg shop/"+ req.body.shop_id+ '/' + req.files.product_video.name + "_thumbnail.jpg", function(err){
var data = {
'thum_src':'shop/'+ req.body.shop_id+ '/' + req.files.product_video.name + "_thumbnail.jpg",
'video_name':req.files.product_video.name,
}
res.send(data);
});
}
});
}
});
};
here is front end code
$('#input_product_video').uploadify({
'formData':{'shop_id':$('#shop_id').val()},
'buttonText' : 'add',
'fileSizeLimit' : '100MB',
'fileObjName' : 'product_video',
'uploader' : '/uploads',
'swf' :'/public/javascripts/lib/uploadify/uploadify.swf',
'onUploadSuccess':function(file,data){
console.log(file);
console.log(JSON.parse(data));
console.log(response);
}
});
You shouldn't need the fs.unlink call because fs.rename is going to move the file to the correct path, not copy it, so if fs.rename succeeds, the temporary file will already be gone. Remove the whole fs.unlink block, which doesn't check for an error anyway. Then you need to make sure in every possible path through the code, you are either calling next(err) with an error or calling res.send. It looks like there are code paths in here where you will not respond and will just let the request time out. Make those changes and see if that gets it working.