renaming uploaded file nodejs and multer - node.js

problem with file name in Multer
i am using express.js and multer to upload images to server. i act like this:
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "../client/member/upload");
},
filename: function (req, file, callback) {
console.log('1', 1);
callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
});
var upload = multer({ storage : storage}).single('userPhoto');
but the problem is that never file name changes.
my uploader handler:
function memberUpload(request, response) {
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "../client/member/upload");
},
filename: function (req, file, callback) {
console.log('1', 1);
callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
});
var upload = multer({ storage : storage}).single('userPhoto');
var folderName = path.join(__dirname, '../', 'client/member/upload');
if (!fs.existsSync(folderName)) {
fs.mkdir(folderName, function (err) {
if (err) {
return response.status(500).send(err);
}
else {
upload(request, response, function (err) {
if (err) {
return response.status(400)
.send('No files were uploaded.');
}
var sentFile = request.files.file,
fileName = (request.files.file && request.files.file.name) ? request.files.file.name : 'test';
sentFile.mv(path.join(__dirname, '../', 'client/member/upload/', fileName), function (err) {
mime.lookup(path.join(__dirname, '../', 'client/member/upload/', fileName)); // => 'text/plain'
if (err) {
return response.status(500)
.send(err);
}
response.send({'location': '../member/upload/' + fileName});
});
});
}
});
}
else {
upload(request, response, function (err) {
if (err) {
return response.status(400)
.send('No files were uploaded.');
}
var sentFile = request.files.file,
fileName = (request.files.file && request.files.file.name) ? request.files.file.name : 'test';
sentFile.mv(path.join(__dirname, '../', 'client/member/upload/', fileName), function (err) {
mime.lookup(path.join(__dirname, '../', 'client/member/upload/', fileName)); // => 'text/plain'
if (err) {
return response.status(500)
.send(err);
}
response.send({'location': '../member/upload/' + fileName});
});
});
}
}
the file save into correct directory with name "blobid0.jpeg", "blobid1.png" and so on ...
what is my fault?

Here is my code for uploading any file(pdf, txt, png) to server.Hope this will help you.
exports.saveMedia = ((req, res) => {
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, (config.const.path.base + config.const.path.productReviewMedia));
},
filename: (req, file, callback) => {
callback(null, Date.now() + '-' + file.originalname);
}
});
const upload = multer({storage: storage}).any('file');
upload(req, res, (err) => {
if (err) {
return res.status(400).send({
message: helper.getErrorMessage(err)
});
}
let results = req.files.map((file) => {
return {
mediaName: file.filename,
origMediaName: file.originalname,
mediaSource: 'http://' + req.headers.host + config.const.path.productReviewMedia + file.filename
}
});
res.status(200).json(results);
});
});

Related

NodeJS application doesn't upload files

I am developing a very simple JavaScript application with NodeJS. Simply upload files and view their content by paragraphs.
The problem is that every time I upload a file, I get the error "No files were uploaded." which corresponds to the following lines:
app.post('/upload_file', (req, res) => {
if (!req.files || !req.files.filetoupload) {
return res.status(400).send('No files were uploaded.');
}
[...]
}
This is the complete code:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
if (!fs.existsSync('./db')) {
fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
fs.mkdirSync('./uploads');
}
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the paragraphs database.');
});
db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
if (err) {
console.error(err.message);
}
console.log('Created paragraphs table.');
});
app.get('/', (req, res) => {
res.send('<h1>Hello World!</h1>' +
'<meta charset="utf-8">' +
'Upload File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
});
app.get('/file_uploading', (req, res) => {
res.send('<h1>File Uploading</h1>' +
'<meta charset="utf-8">' +
'<form action="/upload_file" method="post" enctype="multipart/form-data">' +
'<input type="file" name="filetoupload"><br>' +
'<input type="submit">' +
'</form>');
});
app.post('/upload_file', (req, res) => {
if (!req.files || !req.files.filetoupload) {
return res.status(400).send('No files were uploaded.');
}
let file = req.files.filetoupload;
let filename = file.name;
fs.writeFile('./uploads/' + filename, data, (err) => {
if (err) {
return console.log(err.message);
}
console.log('The file has been saved!');
});
file.mv('./uploads/' + filename, (err) => {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded!<br>' +
'Upload Another File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
});
fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
if (err) {
return console.log(err.message);
}
let lines = data.split('\n');
for (let i = 0; i < lines.length; i++) {
db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
if (err) {
return console.log(err.message);
}
});
}
});
});
app.get('/visualize_paragraphs', (req, res) => {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
res.write('<h1>Visualize Paragraphs</h1>');
res.write(row.text + '<br>');
});
res.end();
});
});
app.get('/tag_paragraphs', (req, res) => {
let paragraph_id = req.query.paragraph_id;
let tag = req.query.tag;
if (paragraph_id && tag) {
db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
if (err) {
return console.log(err.message);
}
console.log(`Row(s) updated: ${this.changes}`);
});
res.send('<h1>Tag Paragraphs</h1>' +
'<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
} else {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
res.write('<h1>Tag Paragraphs</h1>' +
'<table>');
rows.forEach((row) => {
res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
});
res.write('</table>' +
'<form action="/tag_paragraphs" method="get">' +
'<label for="paragraph_id">Paragraph ID:</label>' +
'<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
'<label for="tag">Tag:</label>' +
'<input type="text" id="tag" name="tag"><br>' +
'<input type="submit" value="Submit">' +
'</form>');
res.end();
});
}
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});
Can you help me? What am I doing wrong?
Try uploading file using Multer Middle ware it will ease out your life, I am attaching a sample code which I used in one of my Project
const express = require('express');
const fs = require('fs');
const Log = require('../utils/Log');
const User = require('../db/models/user_model');
const BandCode = require('../db/models/band_codes')
const UserRouter = new express.Router();
const Response = require('../const/Response');
const auth = require('../middleware/auth');
const path = require('path');
const multer = require('multer')
const sharp = require('sharp')
const appleReceiptVerify = require('node-apple-receipt-verify');
const validator = require('validator');
const { sendPasswordResetEmail } = require('../emails/account');
const { totp } = require('otplib');
const { isError } = require('util');
const key = process.env.TOTP;
totp.options = { step: 1800 }
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, process.env.PUBLIC)
},
filename: (req, file, cb) => {
cb(null, req.user._id + '' + Date.now() + path.extname(file.originalname))
}
});
const upload = multer({
storage,
limits: {
fileSize: 9000000
},
fileFilter(req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error('Please upload an image'))
}
cb(undefined, true)
}
})
UserRouter.post('/users/avatar', auth, upload.single('avatar'), async (req, res) => {
console.log("User Image Update Request")
const filepath = process.env.BASE_PATH +req.file.filename;
console.log(filepath)
req.user.imageUrl = filepath;
req.user.avatar = null
// const file = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toFile();
// req.user.avatar = buffer
await req.user.save()
const user = req.user.toObject();
delete user.avatar
delete user.password
delete user.token
delete user.tokens
delete user.socialId
delete user.totop
delete user.buffer
delete user.__v
const response = new Response("SUCCESS", "Image saved", 200, 0, { user });
res.send(response)
}, (error, req, res, next) => {
console.log(error);
res.status(400).send({ error: error.message })
})
module.exports = UserRouter;
From the documentation:
In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.
… and you don't have any such middleware loaded.
Ah, I have had the problem before.
It's probably the form type that's being sent by the client.
I would look into multer!
https://www.npmjs.com/package/multer
I think you'll find your solution with that package
you have to use multer for file upload
router.post('/upload-file', upload.single('image'))
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
cb(null , `${Date.now().toString()}-${file.originalname}`);
}
});
const upload = multer({ storage: storage, limits: { fieldSize: 10 * 1024 * 1024 } });
Answer extracted from question, added in behalf of the asker
This is the solution and the fixed code.
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
const multer = require('multer');
const path = require('path');
// Set up multer
const storage = multer.diskStorage({
destination: './uploads/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
},
});
const upload = multer({
storage,
dest: './uploads/',
limits: {
fileSize: 1000000
},
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
}
});
// Check if the file is a txt file
function checkFileType(file, cb) {
const filetypes = /\.(txt)$/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetypes = 'text/plain'
mimetype = mimetypes === file.mimetype;
if (mimetype && extname) {
return cb(null, true);
} else {
cb('Error: Only txt files are allowed!');
}
}
// Set up express
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Create directories if they don't exist
if (!fs.existsSync('./db')) {
fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
fs.mkdirSync('./uploads');
}
// Connect to the database
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the paragraphs database.');
});
// Create the paragraphs table if it doesn't exist
db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
if (err) {
console.error(err.message);
}
console.log('Created paragraphs table.');
});
// Home page
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
/*
res.write('<h1>Welcome to the Paragraphs App</h1>' +
'Upload a File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
res.end();
*/
});
app.get('/file_uploading', (req, res) => {
res.sendFile(__dirname + '/file_uploading.html');
});
app.post('/upload_file', upload.single('filetoupload'), async (req, res) => {
let filename = req.file.filename;
res.send('File uploaded!<br>' +
'Upload Another File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
if (err) {
return console.log(err.message);
}
let lines = data.split('\r\n');
for (let i = 0; i < lines.length; i++) {
db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
if (err) {
return console.log(err.message);
}
});
}
});
});
app.get('/visualize_paragraphs', (req, res) => {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
res.write('<h1>Visualize Paragraphs</h1>');
res.write(row.text + '<br>');
});
res.end();
});
});
app.get('/tag_paragraphs', (req, res) => {
let paragraph_id = req.query.paragraph_id;
let tag = req.query.tag;
if (paragraph_id && tag) {
db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
if (err) {
return console.log(err.message);
}
console.log(`Row(s) updated: ${this.changes}`);
});
res.send('<h1>Tag Paragraphs</h1>' +
'<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
} else {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
res.write('<h1>Tag Paragraphs</h1>' +
'<table>');
rows.forEach((row) => {
res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
});
res.write('</table>' +
'<form action="/tag_paragraphs" method="get">' +
'<label for="paragraph_id">Paragraph ID:</label>' +
'<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
'<label for="tag">Tag:</label>' +
'<input type="text" id="tag" name="tag"><br>' +
'<input type="submit" value="Submit">' +
'</form>');
res.end();
});
}
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});

express body-parser and multer value receiving issue?

I am giving post request /product/create with some value and an image.
if I console every value before
upload(req, res, (err) => {})
it is showing properly with out image info.
if I receive the value after upload(req, res, (err) => {})
No value is showing.
Full post request code:
app.post('/product/create', (req, res) => {
let filename;
upload(req, res, (err) => {
if(err){
res.render('index', {
msg: err
});
} else {
if(req.file == undefined){
res.render('index', {
msg: 'Error: No File Selected!'
});
} else {
res.render('index', {
msg: 'File Uploaded!',
filename = req.file.filename;
});
}
}
});
const product = {
title : req.body.title,
desc : req.body.desc,
image : filename,
}
});
configuring Multer:
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function(req, file, cb){
cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage,
limits:{fileSize: 1000000},
fileFilter: function(req, file, cb){
checkFileType(file, cb);
}
}).single('myImage');
function checkFileType(file, cb){
const filetypes = /jpeg|jpg|png|gif/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
}
Multer does not support 'req.file.filename' outside upload function. As filename, originalname, fieldname etc is inbuild API of multer. It is limited to upload function only.
Now, if you are trying to upload product values inside database then you have to create an insert function inside multer upload function only.

Multer file upload doesn't work with swaggerExpress

I'm trying to upload multipart form data using multer. I'm using swagger express middleware for my APIs. Without swagger everything was working. But with swagger, file is not uploaded. There's no validation error, but it simply doesn't upload file. Here's some code that you may want to see:
app.js
SwaggerExpress.create(config, function(err, swaggerExpress) {
if (err) { throw err; }
swaggerExpress.register(app);
var port = 8850;
https.createServer(options, app).listen(port, function () {
console.log('Bus993 server started # %s!', port);
});
});
upload function
function uploadImage(req, res, multer){
console.log("here", req.files);
//ABOVE SHOWS A VALID FILE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
console.log("fILE", file);
//THIS IS NOT PRINTED
cb(null, '../../public/images');
},
filename: function (req, file, cb) {
console.log(file);
//THIS IS NOT PRINTED
cb(null, file.originalname.replace(/[.]{1}[a-zA-Z]+$/, "") + '_' + moment().format('X') + getExtension(file));
}
});
var upload = multer({storage: storage, fileFilter: fileFilter}).single('imageFile');
upload(req, res, function (err) {
if (err) {
res.status(422).json(
{
status: "error",
data: {error: err.message},
message: "Image upload failed."
}
);
} else {
res.status(200).json(
{
status: "success",
data: "",
message: "Image uploaded successfully."
}
);
}
});
function fileFilter(req, file, cb) {
console.log("fILE", file);
if ((file.mimetype != 'image/jpeg' && file.mimetype != 'image/png' && file.mimetype != 'image/gif') || file.size > 8000) {
cb(new Error('Invalid file.'), false);
} else {
cb(null, true);
}
}
function getExtension(file) {
var res = '';
if (file.mimetype === 'image/jpeg') res = '.jpg';
if (file.mimetype === 'image/png') res = '.png';
if (file.mimetype === 'image/gif') res = '.gif';
return res;
}
}
So, the problem seems that file is undefined here since when I'm using swagger. Earlier it was fine. But now it returns status:success but image was never uploaded.
Am I doing something wrong?
swaggerExpress uploading a file local/s3 successful
following setups are:
1. in swagger file(yaml)
/s3/upload:
x-swagger-router-controller: s3/upload
post:
operationId: upload
tags:
- S3
consumes:
- multipart/form-data
parameters:
- in: formData
name: file
description: The file to upload
type: file
2.add extra middleware
SwaggerExpress.create(config, function(err, swaggerExpress) {
if (err) { throw err; }
// install middleware
app.use(SwaggerUi(swaggerExpress.runner.swagger));
// install extra middleware
app.use(function (req, res, next) {
if(req.file){
req.files = req.file
}else{
req.files = {}
}
next();
});
// install middleware
swaggerExpress.register(app);
console.log("Listening on port: "+ port)
app.listen(port);
});
3.controller using multer,multerS3 and aws-sdk
define middleware before controller
s3 object
const uploadFile = multer({
storage: multerS3({
s3: s3,
bucket: 'bucket_name',
metadata: function (req, file, cb) {
cb(null, {fieldName: file.fieldname});
},
key: function (req, file, cb) {
cb(null, file.originalname)
}
})
}).fields([{name: "file"}])
controller.upload = async function(req, res, next){
console.log("---------upload---------------");
try{
uploadFile(req, res, function (error) {
if (error) {
console.log(error);
res.json({
result: "Error",
status: false
})
}else{
console.log('File uploaded successfully.',req.files);
res.json({
result: req.files.file[0],
status: true
})
}
});
}catch(e){
res.json({
message: "Error"
})
}
}
enter image description here

Rename uploaded images using MULTER

I am uploading the images using multer. They all are given random names (dec93b9f333c7a731723b06ce73c0bbc.jpg), which is very bad for SEO... Can you guys help me out, how to save the images with the pattern: 'fixed-name'+'random-name'.extension. Then at least part of the file would be readable for the google. Thanks!
app.set('images', '/var/www/images');
app.use(app.get('images'), express.static(app.get('images')));
var multerForImage = multer({
dest: app.get('images'),
onParseStart: function (file) {
console.log("Started parsing file stream", file);
},
onFileUploadStart: function (file) {
console.log('File recieved: ', file.originalname);
},
onFileUploadComplete: function (file, req, res) {
console.log("File upload complete");
var path = app.get('images') + "/" + file.name;
var user = req.session.user;
res.json({
success: true,
data: path
});
},
onFileUploadData: function (file, data, req, res) {
console.log('Data recieved for file upload');
},
onParseEnd: function (req, next) {
console.log("Parsing data end for file upload");
}
});
You can use the storage configuration.
app.set('images', '/var/www/images');
app.use(app.get('images'), express.static(app.get('images')));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, app.get('images'))
},
filename: function (req, file, cb) {
const randomPart = uuidV4(); // use whatever random you want.
const extension = file.mimetype.split('/')[1];
cb(null, 'fixed-name'+ randomPart + `.${extension}`)
}
})
var multerForImage = multer({
storage: storage,
...

How can I dynamically create userdefined folder for file upload using multer in nodejs?

i want to upload the file into a folder which should be get from form data submit by user. which is req.body.coursename
/*conditions for directory check*/
var isvalidate = function (data) {
var data = data;
var dir = '../uploads'+'/'+data;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
return dir;
} else {
return dir;
}
};
/*multer*/
var date = moment().format('YYYY-MM-DD');
var storage = multer.diskStorage ({
destination: function (req, file, callback) {
console.log("filename upload",file.originalname);
callback(null, isvalidate(req.body.coursename));
},
filename: function (req, file, callback) {
//console.log("filename upload",file.originalname);
callback(null, date+ '-' +file.originalname );
}
});
var data = multer({ storage : storage }).any();
/*file upload*/
router.post('/create',function(req, res) {
console.log(req.body);
data(req, res, function(err) {
console.log(req.body);
//isvalidate (req.body.coursename);
if (err) {
res.json({error_code:1,err_desc:err});
return;
}
});
});
How can I create a folder with the name req.body.coursename for file upload?
You can't but you can move the file to other locations after the file is uploaded. You could make your storage object a module and change the directory dynamically via init
var multer = require('multer'); // middleware for handling multipart/form-data,
// Constructor
module.exports = function (name) {
try {
// Configuring appropriate storage
var storage = multer.diskStorage({
// Absolute path
destination: function (req, file, callback) {
callback(null, './uploads/'+name);
},
// Match the field name in the request body
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
return storage;
} catch (ex) {
console.log("Error :\n"+ex);
}
}
OR Use busboy
var Busboy = require('busboy');
var fs = require('fs');
app.post('.....',fucntion(req, res, next){
var busboy = new Busboy({ headers: req.headers });
busboy.on('field', function(fieldname, val) {
req.body[fieldname] = val;
});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
fstream = fs.createWriteStream("path/desiredImageName");
file.pipe(fstream);
fstream.on('close', function() {
file.resume();
});
})
return req.pipe(busboy);
})
OR you can use changedest
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
});

Resources