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");
}
})
Related
Multer cannot store the file, where the destination is in public/my-uploads
const express = require('express');
const app = express();
const multer = require('multer');
let storage = multer.diskStorage({
destination: '/public/my-uploads',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({dest:'storage/'}).single('file');
app.post('/upload', upload, (req , res) => {
console.log(req.files) // this does log the uploaded image data.
})
Try this File Storage For Save image in Local
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(
null,
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname
);
},
});
This happens because you are using windowsOS and where you learned it may be using macOS in windows Path have to setted as mentioned in the above code.
You simply set the file name as given in my answer and destination is root dir "./images"...
I want to pass an image from the app to the server. But when I open the picture folder, no image found. I think the image able to send to the server but cannot store the image to the picture folder. I hope you guys can help me solve this problem. Thank you in advance
Project Structure
|
|-db
|-node_modules
|-app.js
|-picture
|-routes
|-perkhidmatan_rumput
|-rumput.js
rumput.js
var router = require('express').Router();
var multer = require('multer');
var upload = multer({ storage: storage })
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null,'../../picture')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
router.post('/api/PostPemantauanPerkhidmatanPotingRumput/:zon/:syarikat/:alamat_syarikat/'+
':nama_penyelia/:taman/:bulan/:tahun/:masa/:timeAMPM/:pusingan/:status/:catatan/:state/'+
':entryOperator', upload.single('image'),(req,res,next) =>{
console.log(req.file)
})
destination :
cb(null,'../../../picture')
and filename will be :
let path = require('path');
cb(null, file.fieldname + '-' + Date.now()+path.extname(file.originalname))
Able to solve the problem.
var router = require('express').Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null,'picture/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
var upload = multer({ storage })
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!
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 });
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/`;