I'm trying to upload any file using Multer package. It's working fine when I use following code in my server.js file.
var express = require('express'),
app = express(),
multer = require('multer');
app.configure(function () {
app.use(multer({
dest: './static/uploads/',
rename: function (fieldname, filename) {
return filename.replace(/\W+/g, '-').toLowerCase();
}
}));
app.use(express.static(__dirname + '/static'));
});
app.post('/api/upload', function (req, res) {
res.send({image: true, file: req.files.userFile.originalname, savedAs: req.files.userFile.name});
});
var server = app.listen(3000, function () {
console.log('listening on port %d', server.address().port);
});
What I want is to store file at different locations. I had tried following code but it does not work for me.
var express = require('express'),
app = express(),
multer = require('multer');
app.configure(function () {
app.use(multer({
//dest: './static/uploads/',
rename: function (fieldname, filename) {
return filename.replace(/\W+/g, '-').toLowerCase();
}
}));
app.use(express.static(__dirname + '/static'));
});
app.post('/api/pdf', function (req, res) {
app.use(multer({ dest: './static/pdf/'}));
res.send({image: true, file: req.files.userFile.originalname, savedAs: req.files.userFile.name});
});
app.post('/api/image', function (req, res) {
app.use(multer({ dest: './static/image/'}));
res.send({image: true, file: req.files.userFile.originalname, savedAs: req.files.userFile.name});
});
app.post('/api/video', function (req, res) {
app.use(multer({ dest: './static/video/'}));
res.send({image: true, file: req.files.userFile.originalname, savedAs: req.files.userFile.name});
});
var server = app.listen(3000, function () {
console.log('listening on port %d', server.address().port);
});
Means, if I hit http://localhost:3000/api/pdf file should store at 'pdf' folder, if I hit http://localhost:3000/api/video file should store at 'video' folder.
Is there any way to achieve this aim?
Thank you in advance.
Update
Quite a few things have changed since I posted the original answer.
With multer 1.2.1.
You need to use DiskStorage to specify where & how of the stored file.
By default, multer will use the operating system's default directory. In our case, since we are particular about the location. We need to ensure that the folder exists before we could save the file over there.
Note: You are responsible for creating the directory when providing destination as a function.
More here
'use strict';
let multer = require('multer');
let fs = require('fs-extra');
let upload = multer({
storage: multer.diskStorage({
destination: (req, file, callback) => {
let type = req.params.type;
let path = `./uploads/${type}`;
fs.mkdirsSync(path);
callback(null, path);
},
filename: (req, file, callback) => {
//originalname is the uploaded file's name with extn
callback(null, file.originalname);
}
})
});
app.post('/api/:type', upload.single('file'), (req, res) => {
res.status(200).send();
});
fs-extra for creating directory, just in case if it doesn't exists
Original answer
You can use changeDest.
Function to rename the directory in which to place uploaded files.
It is available from v0.1.8
app.post('/api/:type', multer({
dest: './uploads/',
changeDest: function(dest, req, res) {
var newDestination = dest + req.params.type;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
throw new Error('Directory cannot be created because an inode of a different type exists at "' + dest + '"');
}
return newDestination
}
}), function(req, res) {
//set your response
});
Multer is a middleware so you can pass it like this :
app.post('/test/route', multer({...options...}), module.someThing)
or
app.post('/test/route', multer({...options...}), function(req, res){
........some code ......
});
You can make a function like so:
var uploadFnct = function(dest){
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
cb(null, './public/img/'+dest+'/');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]);
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
return upload;
};
And then use it in your upload route:
//Handle the library upload
app.post('/app/library/upload', isAuthenticated, function (req, res) {
var currUpload = uploadFnct('library');
currUpload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null, filename: req.file.filename});
});
});
I tried the solutions shown here but nothing helped me.
ChangeDest attr is not available anymore (As Sridhar proposes in his answer)
I want to share my solution (I am using express 4.13 and multer 1.2):
Imports:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var multer = require('multer');
Storage variable (see documentation here)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
var dest = 'uploads/' + req.params.type;
var stat = null;
try {
stat = fs.statSync(dest);
} catch (err) {
fs.mkdirSync(dest);
}
if (stat && !stat.isDirectory()) {
throw new Error('Directory cannot be created because an inode of a different type exists at "' + dest + '"');
}
cb(null, dest);
}
});
Initializing Multer:
var upload = multer(
{
dest: 'uploads/',
storage: storage
}
);
Using it!
router.use("/api/:type", upload.single("obj"));
router.post('/api/:type', controllers.upload_file);
var storage = multer.diskStorage({
destination: function (req, file, cb) {
if (req.path.match('/pdf')) {
cb(null,<destination>)
}
},
filename: function (req, file, cb) {
}
})
This works in case, the path is unique. You can modify (checking for the end point {req.path}) according to your needs. Though this solution is not dynamic.
we can get path as
const basePath=`${req.protocol}://${req.get("host")}/public/uploads/`;
Related
I've developed a small web server to upload pictures.
Now I would like to use the original name of the picture and move the picture into a folder. the name of the folder is in the req.body.
Ok, the upload works, but where is the point to rename oand move the picture?
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: __dirname + '/uploads/images' });
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.post('/upload', upload.single('image'), (req, res) => {
console.log(req.file.originalname)
console.log(req.body.foldername)
if (req.file) {
res.json(req.file);
}
else throw 'error';
});
app.listen(PORT, () => {
console.log('Listening at ' + PORT);
});
This is your question answer to rename a file before it upload
var storage = multer.diskStorage({
// Where to save
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
// File name
filename: function (req, file, cb) {
cb(null, file.originalname) // file.originalname will give the original name of the image which you have saved in your computer system
}
})
var upload = multer({ storage: storage })
In node a can make something like this with and excel file in my directory.
app.post('/api/xlstojson', function(req, res) {
var workbook = XLSX.readFile('tc2.xls');
var sheet_name_list = workbook.SheetNames;
res.json(XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]));
});
I want to test file uploading with postman. There I select POST, form-data, in key I select file instead of text and then in value I upload the tc2.xls file.
In my code I have something like this
app.post('/api/xlstojson', function(req, res) {
var workbook = XLSX.readFile(req.body.file);
var sheet_name_list = workbook.SheetNames;
res.json(XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]));
});
But I get TypeError: path must be a string or Buffer. How should I modify my code to make this work?
Update:
I have been trying with multer, but the file does not appear in the folder
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
app.post('/upload', function(req, res) {
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
TypeError: path must be a string or Buffer
You're getting this error because you're not passing the file location. For this to work, you need to pass the location of the file within the upload/ folder
'use strict';
const XLSX = require('xlsx');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length - 1]);
}
});
var upload = multer({ //multer settings
storage: storage
});
function validate(req, res, next) {
if (!req.file) {
return res.send({
errors: {
message: 'file cant be empty'
}
});
}
next();
}
app.post('/api/xlstojson', upload.single('file'), validate, function (req, res) {
const fileLocation = req.file.path;
console.log(fileLocation); // logs uploads/file-1541675389394.xls
var workbook = XLSX.readFile(fileLocation);
var sheet_name_list = workbook.SheetNames;
return res.json({
json: XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]])
});
});
You need to upload the xls file from postman
I am a novice at NodeJS and I created a service to upload images to a shared location. However, I need to set the upload folder dynamically based on the user id: for e.g. the folder will be /uploads/{userid}/file.txt
I am not sure how to do it and I have been searching today with no luck.
The NodeJS service looks like:
var express = require('express')
var multer = require('multer')
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./Uploads");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + "_" + Date.now() + "_" +
file.originalname);
}
});
var upload = multer({ Storage: Storage })
var app = express()
app.post('/upload', upload.array('uploads[]', 12), function (req, res, next)
{
return res.end("Files uploaded sucessfully!.");
})
Thank you for the help.
Try this
app.use(multer({
dest: './uploads/',
"rename" : function (fieldname, filename, req, res) {
return path.join(fieldname, req.params.user_id+".txt");
}
})
I have stored images with multer on express app server. But I am not getting that images to use in my html files.
Code to upload file.
var multer = require("multer")
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname+'/public/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now()+file.originalname)
}
})
app.post('/add/details', upload.any(), function(req,res){
var data = req.body;
data.propic = req.files[0].path;
res.render('index',{
"data": data
});
})
In index file I am setting src of img to data.propic but it's not showing image.
you can use this
var fileUpload = require('express-fileupload');
router.use(fileUpload());
sampleFile = req.files.team_image;
file_name = sampleFile.name;
sampleFile.mv('public/storage/'+file_name, function(err) {
if (err) {
if (err) throw err;
}
});
Since you are saving the images in public/images folder, you can take advantage of express.static for serving these newly uploaded files automatically.
var express = require('express');
var multer = require("multer")
var app = express();
//all static contents inside the given folder will be accessible
//e.g. http://example.com/public/uploads/test.png
app.use(express.static(__dirname+'/public/uploads'));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname+'/public/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now()+file.originalname)
}
});
app.post('/add/details', upload.any(), function(req,res){
var data = req.body;
// path of uploaded file.
data.propic = '/public/uploads/'+req.files[0].filename;
res.render('index',{
"data": data
});
});
Assume that you are using jade as view engine, you can embed img as following:
img(src=data.propic) // it's equivalent to http://example.com/public/uploads/test.png
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 });