nodejs multer is getting req.file but not uploading it to destination - node.js

multer.js
var path = require("path"),
multer = require("multer");
const storage = multer.diskStorage({
destination: function(req, file, next){
next(null, '../public/imgs/');
return;
},
filename: function(req, file, cb){
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage
});
module.exports = upload;
router.js
//handle createPartner route
router.post("/partner/new", upload.single('image'), function(req, res){
console.log(req.file);
console.log(req.body);
req.body.Partner["image"] ="/static/imgs/"+req.file.filename;
req.body.Partner.body = req.sanitize(req.body.Partner.body);
Partner.create(req.body.Partner, function(err, createdPartner){
if(err){
console.log(err);
res.redirect("/admin/partner/new");
}else{
res.redirect("/partners");
}
});
});
I get the following console.log
{ fieldname: 'image',
originalname: 'fb.png',
encoding: '7bit',
mimetype: 'image/png',
destination: '../public/imgs/',
filename: 'image-1521727739861.png',
path: '../public/imgs/image-1521727739861.png',
size: 21532 }
{ Partner: { name: 'test', bio: 'test', image: '', website: 'test' } }
so multer does get the file but it doesn't upload it to the destination! The permissions for /public and /public/imgs are 777. Everywhere I searched uses the other method for multer but that way I'll have to specify (single/multiple/any) in advance which isn't right.

You need to include the absolute path as I mentioned in comments.
You can easily do this by utilising path.join like follows:
var path = require('path');
var dir = path.join(__dirname, '../public/imgs')
That will concatenate __dirname which is the absolute path of the current file with your images file.

Related

Multer 'storage' option does not work while 'dest' one does

I'm using Multer to upload and store files. If I use the dest option files upload to my /uploads folder with no problem. Whilst this works, it's saving the uploads like 2eb3f1a6def453f7a461c5de353b06f8 so I want to use the storage option, but for some reason this doesn't work or me and the files upload (logged in console), but wont save to the folder.
I've tried a few different ways of achieving this and none work. Can anyone point out what might be wrong?
{
fieldname: 'attachments',
originalname: 'myFile.pdf',
encoding: '7bit',
mimetype: 'application/pdf',
destination: 'uploads/',
filename: '2eb3f1a6def453f7a461c5de353b06f8',
path: 'uploads/2eb3f1a6def453f7a461c5de353b06f8',
size: 57638
}
const express = require('express');
const app = express();
const multer = require("multer");
const path = require('path');
// const upload = multer({ dest: "uploads/" }); // this works, file saves to /uploads
var upload = multer({ storage: storage }); // this doesnt work/ files dont save to /uploads
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
var storage = multer.diskStorage({
destination: function(req, file, cb) {
// cb(null, 'uploads/');
// cb(null, __dirname + '/uploads');
cb(null, './uploads');
},
filename: function (req, file, cb) {
// cb(null , file.originalname);
// cb(null, file.fieldname + '-' + Date.now());
// By default, multer removes file extensions so let's add them back
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
// var upload = multer({ storage: storage });
app.post('/', upload.array('attachments') , (req, res) =>{
try {
res.send(req.files);
console.log('body', req.body);
console.log('files', req.files);
} catch(error) {
console.log(error);
res.send(400);
}
});
module.exports = {
path: '/api/upload',
handler: app
};
Declaring var upload = multer({ storage: storage }) after having it defined with multer.diskStorage was enough to fix OP's issue.

Same Image not uploading in express

I am trying to upload an image using express but I am facing two problems, first, whenever I upload the same image again it's not getting uploaded and secondly after uploading any single image a file with image also uploading. Here is my code.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
var file = __dirname +"/images" + "/" + req.file.originalname;
fs.readFile( req.file.path, function (err, data) {
fs.writeFile(file, data, function (err,data) {
if( err ){
console.error( err );
response = {
message: 'Sorry, file couldn\'t be uploaded.',
filename: req.file.originalname
};
}else{
response = {
message: 'File uploaded successfully',
filename: req.file.originalname
};
}
res.end( JSON.stringify( response ) );
});
});
})
The uploads.single("file") middleware Will handle the file upload. You don't have to specifically fs.read and fs.write the file.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
EDIT: The above code will upload the file with hex string as filename without any extension.
In order to add rename function you need to use diskStorage. Here is the code taken from this github issue page.
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './images/')
},
filename: function (req, file, cb) {
crypto.pseudoRandomBytes(16, function (err, raw) {
cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype)); //this is the rename func
});
}
});
var uploads = multer({ storage: storage });
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
Now you can use the uploads variable as middleware as shown in the above snippet.
you can edit the filename: function (req, file, cb) { .. } according to your needs. Now the filename will be, <16characterhexstring>.ext
another way to handle it will be not using middleware and using multer manually with below options :
try {
var storage = multer.diskStorage({
destination: function(request, file, callback) {
//define folder here by fs.mkdirSync(anyDirName);
},
filename: function(req, file, callback) {
callback(null, anyFileName);
},
limits: self.limits
});
var upload = multer({
storage: storage,
fileFilter: function(request, file, callback) {
// here you can filter out what not to upload..
}
}).any();
upload(request, response, callback);
} catch (e) {
}
hope this helps!

Accesing filenames in req.files created by Multer, doing stuff to newly uploaded files

I'm new to web development. I have a multi-file upload on a page. The files are successfully uploaded with multer into my 'public/uploads' folder.
How do I access the filenames that I just uploaded using the req.files that multer creates? The result is not an array, although the multer docs say for multiple files, req.files will contain an array.
I feel like I have something set up incorrectly.
Here's console.log(req.files). as you can see the backets are not comma separated.
[ { fieldname: 'file',
originalname: 'acschemrev5b00690.jpeg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'public/uploads',
filename: '1484769679031-acschemrev5b00690.jpeg',
path: 'public/uploads/1484769679031-acschemrev5b00690.jpeg',
size: 79299 } ]
[ { fieldname: 'file',
originalname: 'acschemrev5b00701.jpeg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'public/uploads',
filename: '1484769679047-acschemrev5b00701.jpeg',
path: 'public/uploads/1484769679047-acschemrev5b00701.jpeg',
size: 127608 } ]
[ { fieldname: 'file',
originalname: 'acschemrev5b00703.jpeg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'public/uploads',
filename: '1484769679109-acschemrev5b00703.jpeg',
path: 'public/uploads/1484769679109-acschemrev5b00703.jpeg',
size: 117312 } ]
Here's my server app.js file:
var express = require('express');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
var multer = require('multer');
// var upload = multer({ dest: 'uploads/' });
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads')
},
filename: function (req, file, cb) {
// cb(null, file.fieldname + '-' + Date.now());
cb(null, Date.now() + "-" + file.originalname);
// cb(null, file.originalname);
}
});
var upload = multer({ storage: storage });
// set the view engine to pug
app.set('view engine', 'pug');
app.use(express.static(__dirname + '/public'));
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
app.get('/', function (req, res) {
res.render('index');
});
// from multer
app.post( '/file-upload', upload.any(), function( req, res, next ) {
// Metadata about the uploaded file can now be found in req.file
res.send(req.files);
// console.log(req.files);
currentFiles = req.files;
console.log(req.files);
app.post('/crop-images')
});
I need to process the files that I just uploaded. What is the best way to do this? Do I need to create an array of each filename and then process each one? How do I get their names out of req.files?
Thanks!
If you want to retrieve filenames from the req.files, you could just map that over it like that:
var filenames = req.files.map(function(file) {
return file.filename; // or file.originalname
});
For those using Typescript, it will show errors if mapping over req.files. To overcome this, you can use the below:
(req.files as Array<Express.Multer.File>).map(...)
or
(req.files as Express.Multer.File[]).map(...)
For typescript, this worked for me.
const filenames = req.files! as Array<Express.Multer.File>
const file_names = filenames.map(file => file.filename)

Multer not adding file extension

I'm working on a Node.js/MongoDB based website and i'm trying to upload images directly on server using Express, Jade, and Multer, but no matter what i do, i can't achive to upload the file with extension.
I've got this on my app.js file:
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
var upload = multer({ storage: storage });
var app = express();
mongoose.connect("mongodb://localhost/primera_pagina");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(multer({dest: "./uploads"}).single("image_avatar"));
var productSchema = {
title:String,
description:String,
imageURL:String,
pricing:Number
};
var Product = mongoose.model("Product", productSchema);
app.set("view engine","jade");
app.use(express.static("public"));
app.get("/",function(req,res){
res.render("index");
});
app.post("/productos",function(req,res){
if(req.body.password == "123"){
var data = {
title: req.body.title,
description: req.body.description,
imageURL: "image_avatar",
pricing: req.body.pricing
}
var product = new Product(data);
console.log(req.file)
}else{
res.render("index");
}
});
app.get("/productos/new",function(req,res){
res.render("productos/new");
});
app.listen(8080);
Any idea? I've search on Internet and tried every single method to add file extension with multer, but none has worked.
Multer strips the file extension for both security and collision reasons. For a workaround, try this:
var path = require('path')
var multer = require('multer')
var mime = require('mime-types')
var storage = multer.diskStorage({
destination: './uploads/',
filename: function (req, file, cb) {
crypto.pseudoRandomBytes(16, function (err, raw) {
if (err) return cb(err)
cb(null, raw.toString('hex') + mime.extension(file.mimetype))
})
}
})
var upload = multer({ storage: storage })
(from https://github.com/expressjs/multer/issues/170#issuecomment-123402678)
It assigns a random file name, but keeps the file extension in tact.
You should also be using the authorize field in multer, since it looks like you only want files when the user has the correct password. Do something like this:
var upload = multer({ storage: storage }, limits : { fileFilter: authorize });
function authorize(req, file, cb) {
if (req.body.password == PASS) {
cb(null, true); //accept
} else {
cb(null, false); //reject
}
}
This will only save the file to disk if the user has inputted the correct password.
You can pass the right parameters for Multer like this in order to save the file extension:
var multer = require('multer');
var path = require('path')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname))
}
})
var upload = multer({ storage: storage });

Node/Multer Get Filename

I am using the following to upload files to a directory via Multer. It works great, but I need to perform some actions after upload that require the name of the file I just posted to the "upload" directory. How do I get the name of the file I just posted?
// Multer storage options
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'upload/');
},
filename: function(req, file, cb) {
cb(null, file.originalname + '-' + Date.now() + '.pdf');
}
});
var upload = multer({ storage: storage });
app.post('/multer', upload.single('file'), function(req, res) {
// Need full filename created here
});
var express=require("express");
var app=express();
var multer=require("multer");
var upload=multer({dest:"uploads/"});
app.post("/multer", upload.single("file"), function(req,res){
console.log(req.file.filename);
});
request.file gives the following stats, from which you would just need to pick request.file.originalname or request.file.filename to get the new filename created by nodejs app.
{
fieldname: 'songUpload',
originalname: '04. Stairway To Heaven - Led Zeppelin.mp3',
encoding: '7bit',
mimetype: 'audio/mp3',
destination: './uploads',
filename: 'songUpload-1476677312011',
path: 'uploads/songUpload-1476677312011',
size: 14058414
}
Eg, in nodejs express mvc app with ecma-6,
var Express = require('express');
var app = Express();
var multipartUpload = Multer({storage: Multer.diskStorage({
destination: function (req, file, callback) { callback(null, './uploads');},
filename: function (req, file, callback) { callback(null, file.fieldname + '-' + Date.now());}})
}).single('songUpload');
app.post('/artists', multipartUpload, (req, resp) => {
val originalFileName = req.file.originalname
console.log(originalFileName)
}
Accessing uploaded files data differs in Multer, depending whether you are uploading single or multiple files. Access data like so:
uploading single file:
req.file
uploading multiple files:
req.files
I found the answer on github, you have access to it in
res.req.file.filename
See there for more informations https://github.com/expressjs/multer/issues/302
app.post('/multer', upload.single('file'), function(req, res) {
// Need full filename created here
const file = req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
res.send(file) #Here
});
You need recover file from this line
res.send(file)
using file.filename
This output sample
{
"fieldname": "myFile",
"originalname": "isc te esta esperando.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "uploads",
"filename": "myFile-1602293858948.eaf",
"path": "uploads/myFile-1602293858948.eaf",
"size": 297720
}
using
request.file.filename
fieldname Field name specified in the form
originalname Name of the file on the user's computer
encoding Encoding type of the file
mimetype Mime type of the file
size Size of the file in bytes

Resources