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 })
Related
I have a node.js express code below to upload a image and store into a default folder.
I realised that the file gets renamed and the extension is lost. can some one help me fix this error?
1.How to retain extension and file name
if a zip file is upload, i want to unzip it and upload it
const __basefolder = "C:/Users/user/Desktop";
const express = require('express');
const multer = require('multer');
const upload = multer({dest: __basefolder + '/uploads/images'});
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.post('/upload', upload.single('file'), (req, res) => {
if(req.file) {
res.json(req.file);
}
else throw 'error';
});
app.listen(PORT, () => {
console.log('Listening at ' + PORT );
});
You can define a filename-option in your disk-storage setup, which lets you choose your filename arbitrarily. Since you want the original file-name, you can use file.originalname (note that using this an existing file with the same name will be overwritten though):
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, __basefolder + '/uploads/images');
},
filename: (req, file, cb) => {
cb(null, file.originalname);
}
})
const upload = multer({storage});
Regarding the second question: this has been answered before, see this or that for example.
It simply doesn't save anything to the destination folder i specified.
i tried {storage:storage} instead of {dest: 'storage/'} but it didn't work either.
the image data is actually sent to the server as its console logged. and the dest i specified is created by default but remain empty.
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.
})
***** EDIT ******
HTML
<form onSubmit={this.upload} enctype='multipart/form-data'>
<input type='file' name='image' />
<input type='submit' value='upload' />
</form>
JS
upload(e){
e.preventDefault();
const file = e.target[0].files[0];
console.log(file)
const fm = new FormData();
fm.append('file', file);
console.log(fm)
axios.post('/upload', fm);
}
POSTMAN
Try to catch the error my calling the middleware yourself:
var upload = multer().single('avatar')
app.post('/upload', function (req, res) {
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
return
}
// Everything went fine
})
})
Also, change the storage to this:
let storage = multer.diskStorage({
destination: function(req, file, ca) {
cb(null, '/public/my-uploads');
}
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
It's been a while, the issue was that I wasn't using the multer middleware at all so the callback code for handling the image was never executed.
I didn't know much about how express worked back then.
Seems you are not using the storage variable and use a function for the destination key, as written in the documentation, also you need to pass your file in the input field named field otherwise multer can't store the file, create an storage folder on the same level as the code :
const http = require('http')
const port = 3000
const express = require('express');
const app = express();
const multer = require('multer');
const server = http.createServer(app)
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({ storage }).single('file');
app.post('/upload', upload, (req, res) => {
console.log(req.files) // this does log the uploaded image data.
})
// bind the server on port
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
The name of the "single" in ...single('file') must match the name in the input (containing the file) <input type="file" name='image' /> - and it does not in your example.
Change the multer-part to this ...single('image') - as in the input name='image'
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
);
},
});
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'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/`;