Using multer with nodejs - html

I am trying to upload a file from my page to node server.
I can see form data are arriving in the router on server.
But no file is saved in upload folder.
What am I doing wrong?
//router unit
const express = require('express');
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('chegei')
cb(null, "uploads/")
},
filename: (req, file, cb) => {
console.log('chegei2')
cb(null, Date.now() + "-" + file.ogirinalname)
},
});
module.exports = function (page) {
router.post('/SendMsgBase64', async (req, res) => {
var upload = multer({ storage: storage }).single('userFile');
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.send({ "data": "Error uploading file." });
}
return res.send({ "data": "File is uploaded" });
});
return router
}
//app.js unit
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const WARoutes = require('../routes/WARoutes');
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {
res.sendFile('/index.html');
})
app.use('/whats', WARoutes(this.page));
//html
<form id="uploadForm">
<input type="file" name="userFile" />
<input type="button" value="Upload Image" onclick="uploadFile();">
<span id="status"></span>
</form>
<script>
uploadFile = () => {
var formData = new FormData();
debugger
var logoImg = $('input[name="userFile"]').get(0).files[0];
formData.append('logo', logoImg);
var objArr = [];
objArr.push({ "id": "123", "name": "luiz" });
//JSON obj
formData.append('objArr', JSON.stringify(objArr));
$.ajax({
url: "/whats/SendMsgBase64",
type: "POST",
processData: false,
contentType: "application/x-www-form-urlencoded",
data: formData,
complete: function (data) {
alert("success");
}
})
};
</script>

According to multer's github page, if you have not created the uploads directory, it may go something wrong.
If this is the case, creating the directory on your own or passing a string value to destination property is the solution for you.
https://github.com/expressjs/multer
Note: You are responsible for creating the directory when providing destination as a function. When passing a string, multer will make sure that the directory is created for you.

Related

error column cannot be null, trying to upload file into sql

i am still new in node js, and i am trying to make some backend with file upload/ image upload function that can be stored in sql, i am trying using multer but it cant read my file while testing in postman body. anybody can help me where i do wrong?
here is my controller
const { db } = require('./db');
const bodyParser = require('body-parser');
const getgambar = (req, res) => {
const sqlQuery = "SELECT * FROM gambar";
db.query(sqlQuery, (err, result) => {
if (err) {
console.log(err);
} else {
res.send(result);
console.log(result);
}
});
};
const addgambar = (req,res) => {
const idimg = req.body.idimg;
const gambar = req.file.gambar;
console.log()
const sqlQuery = "INSERT INTO image (idimg,gambar) VALUE (?,?)";
db.query(sqlQuery, [idimg,gambar], (err, result) => {
if (err) {
res.send({
message: "error",
err
})
} else {
res.send({
message: "YES"
})
}
});
};
module.exports = {
getgambar,
addgambar,
};
here is my route
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const ctrl = require('./gambarctrl');
const storange = multer.diskStorage({
destination: './uploads',
filename: (req, file, cb) => {
return cb(null, `${file.fieldname}_${Date.now()}${path.extname(file.originalname)}`)
}
})
const upload = multer({
storange: storange
})
router.get('/image/display', ctrl.getgambar)
router.post('/image',upload.single('gambar'), ctrl.addgambar)
module.exports = router;
and here my index
const { db } = require('./db');
const express = require('express');
const bodyParser = require('body-parser')
const cors = require('cors');
const app = express();
const fileUpload = require('express-fileupload');
const gambarroute = require ('./gambarroute');
const multer = require('multer');
app.use(cors());
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(gambarroute);
app.listen(3000, () => {
console.log('on port 3000!');
});
i am still quite new in node js and i am still searching for tutorial, i appriciate for the help.
Two problems here...
Multer puts the single uploaded file into req.file so you should use
const gambar = req.file; // no `.gambar`
Assuming your DB column is a BLOB or BINARY type, you need to provide a Buffer.
Since you're storing the images within the DB, you don't need to use DiskStorage. Use MemoryStorage instead which provides a Buffer out-of-the-box
const upload = multer({
storage: multer.memoryStorage(), // watch your spelling
})
Then bind the .buffer property in your query.
db.query(sqlQuery, [idimg, gambar.buffer], (err, result) => {
// ...
});
To respond with the image from Express, use something like this
router.get("/image/display/:id", (req, res, next) => {
db.query(
"SELECT `gambar` FROM `image` WHERE `idimg` = ?",
[req.params.id],
(err, results) => {
if (err) {
return next(err);
}
if (!results.length) {
return res.sendStatus(404);
}
// set the appropriate content type
res.set("Content-Type", "image/jpg");
res.send(results[0].gambar);
}
);
});
and from the frontend...
<img src="http://localhost:3000/image/display/some-id" />

how to upload multiple images from multiple fields from HTML form to node js into two folders then to MongoDB?

I have done the first part correctly (upload the images to their folders), but I can't
upload the images to the DB
form.html
the form to upload the images while the user sign up for a new account
<div>
<label for="image">Upload Image</label>
<input type="file" id="image1" name="image1" value="" >
</div><div>
<label for="image">Upload Image</label>
<input type="file" id="image2" name="image2" value="" >
</div>
multer.js
to save the images in the folders
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
if (file.fieldname === 'image1') {
cb(null, './logic/uploads');
}
else if (file.fieldname === 'image2') {
cb(null, './logic/uploadp');
}
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
console.log('New image saved!')
}
});
module.exports = multer({ storage: storage });
route
const express = require('express');
const router = express.Router();
const multer = require('../logic/multer')
const { userSignup, userLogin } = require('../logic/Membership_Application');
router.post('/Register',
multer.fields([
{ name: 'image1', maxCount: 1 },
{ name: 'image2', maxCount: 1 },
]),
userSignup
);
router.post('/login', userLogin);
module.exports = router;
logic (data insertion)
const UsersSchema = await new jcs({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
password: hashedPassword,
nationality: req.body.nationality,
//here is the error(it was working with multer.singel but not with multer,fields)
img: {
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
contentType: 'image/png'
},
img2: {
data: fs.readFileSync(path.join(__dirname + '/uploadp/' + req.file.filename)),
contentType: 'image/png'
}
}).save();
model(Database schema)
const db = require('mongoose');
//Database Creation
const UsersSchema = new db.Schema
({
name: { type: String },
email: { type: String },
phone: { type: String },
password: { type: String },
nationality: { type: String },
img:
{
data: Buffer,
contentType: String,
},
img2:
{
data: Buffer,
contentType: String,
},
})
var Users = db.model("Users", UsersSchema);
module.exports = Users;
app.js
const express = require('express');
const app = express();
require('dotenv/config');
const MembershipApplicationRouter = require('./route/Membership_Application');
const AdminRouter = require('./route/admin')
var bodyParser = require('body-parser');
const cors = require('cors');
const db = require('mongoose');
db.connect('mongodb-link',
{
useNewUrlParser: true,
useUnifiedTopology: true
});
const connection = db.connection;
connection.on('connected', () => { console.log("conected with cloud") });
connection.on('error', () => { console.log("error with database") });
app.use('/admin', AdminRouter);
app.use([
bodyParser.urlencoded({ extended: true }),
express.json(),
express.urlencoded({ extended: true })]);
app.use(cors());
app.use('/membershipApplication', MembershipApplicationRouter);
var port = process.env.PORT || 8080;
app.listen(port, () => {
console.log("Server Up and running");
})
module.exports = app;
I have this error msg
New image saved!
New image saved!
C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
^
TypeError: Cannot read properties of undefined (reading 'filename')
at userSignup (C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79:84)
[nodemon] app crashed - waiting for file changes before starting...
The best practice is to store the file’s location in your server to mongoDB.
So that whenever you to access the file you fetch it’s location then return it back!!

When I upload image through multer , I got image undefined error

I am using it with node and mysql with angular 5.
const express = require('express');
const mysql = require('mysql');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './assets/images/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
const fileFilter = (req, file, cb)=>{
if(file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
cb(null, true);
}
else{
cb(null, false);
}
};
upload = multer({
storage: storage,
limits:{
filesize : 1024 * 1024 * 5
},
fileFilter : fileFilter
});
const app = express();
//DATABASE CONNECTION
const connection = mysql.createConnection({
host: 'localhost',
user:'root',
password: 'root',
database: 'inpblog',
port: 8889
});
// ALLOW CROSS ORIGIN
const corsOptions = {
origin: 'http://localhost:4200',
origin1: 'http://localhost:4202',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.use(cors(corsOptions));
app.use('./assets/images', express.static(path.join(__dirname, 'dist', 'upload')));
const jsonParser = bodyParser.json();
const urlencodedParser = bodyParser.urlencoded({ extended: false });
connection.connect(function(error){
if(!!error){
console.log("error - db not connected");
}
else{
console.log("connected");
}
});
Here i define the code to upload a image in mysql database. through postman its upload a image in destination folder with multer middleware but when i upload a image through ng form its showing error in console."image undefined" and submit the "c:/fakepath/image.jgg" in mysql.
Here is the API to insert the post
app.post('/insertPost', upload.single('txt_blog_image'), jsonParser, (req, res) => {
console.log("image: ", req.file); // working fine only with postman
//console.log("rBody: ", req.body.txt_blog_image); // working fine only with Angular
let blogFields = {
post_author : req.body.txt_blog_author,
post_image : req.body.txt_blog_image
};
let sql = 'INSERT INTO insdb SET ?';
let query = connection.query(sql, blogFields, (err,result)=> {
res.send('New Post added...');
});
});
// Get All Post
app.get('/getallposts', (req, res) => {
let sql = 'SELECT * FROM insdb';
let query = connection.query(sql, (err, results) => {
if(err) throw err;
console.log(results);
res.send(results);
});
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.listen(4202);
Try this way.
var path = require('path');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './assets/images/')
},
filename: function(req, file, callback) {
console.log(file)
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
In your api :
app.post('/getallposts',upload.single("image") , function(req, res) {
let sql = 'SELECT * FROM insdb';
let query = connection.query(sql, (err, results) => {
if(err) throw err;
console.log(results);
res.send(results);
});
})
From Angular side :
let form = new FormData();
form.append('image' , file);
Then console in server side , req.files to check file is coming or not ?
For more information and example please see this link

Send a PDF File with nodemailer via a html form

I have a form in which has an upload file input. I want the user to be able to upload their file and send it via the form. At the moment the PDF file shows attached in the email but doesn't contain any data and won't open etc.
This is what I currently have within the nodemailer options:
let mailOptions = {
from: '"Macwear Clothing" <shop#macwearclothing.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Order Review', // Subject line
text: 'Order Acception', // plain text body
html: output, // html body
attachments: [{'filename': 'needlesheet.pdf', 'content': req.body.needle, 'contentType': 'application/pdf'
}]
};
Client Side index.ejs file
<div class="fileUpload up<%= item.number %>" id="m<%= item.number %>">
<div class="fileUploadContent">
<h2>Customer:
<%= item.email %>
</h2>
<div class="uploadFile">
<input id="needle" type="file" name="needle" value="Upload File >">
</div>
<form method="POST" action="send" name="sendNeedleSheet" enctype="multipart/form-data">
<div class="optionalMessage">
<span>Optional Message:</span>
<textarea class="customTextArea" name="message"></textarea>
<input id="email" name="email" type="hidden" value="<%= item.email %>">
</div>
<div class="modalOptions">
<div class="mButton ok">
<button class="customButton" type="submit">Send</button>
</div>
<div class="mButton cancel">
<span>Cancel</span>
</div>
</div>
</form>
</div>
</div>
app.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const chalk = require('chalk');
const nodemailer = require('nodemailer');
const multer = require('multer');
const app = express();
//View Engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
// Set Static Path
app.use(express.static(path.join(__dirname, '/public')));
// Call JSON
//requestLoop();
// var shopifyAPI = require('shopify-node-api');
// var Shopify = new shopifyAPI({
// shop: 'macwear-clothing-embroidery.myshopify.com', // MYSHOP.myshopify.com
// shopify_api_key: '', // Your API key
// access_token: '' // Your API password
// });
var orderData = null;
// Shopify.get('/admin/orders.json', function(err, data, res, headers){
// app.locals.jsonOrderData = data;
// });
// Shopify.get('/admin/orders/count.json', function(err, data, headers) {
// app.locals.jsonOrderCount = data;
// });
var requestLoop = setInterval(function () {
var request = require("request");
var options_orders = {
method: 'GET',
url: 'https://macwear-clothing-embroidery.myshopify.com/admin/orders.json',
headers: {
'Postman-Token': '',
'Cache-Control': 'no-cache',
Authorization: ''
}
};
var options_order_count = {
method: 'GET',
url: 'https://macwear-clothing-embroidery.myshopify.com/admin/orders/count.json',
headers: {
'Postman-Token': '',
'Cache-Control': 'no-cache',
Authorization: ''
}
};
request(options_orders, function (error, response, body) {
if (error) throw new Error(error);
jsonOrderData = JSON.parse(body);
//console.log(body);
});
request(options_order_count, function (error, response, body) {
if (error) throw new Error(error);
jsonOrderCount = JSON.parse(body);
//console.log(body);
});
}, 60000);
app.get('/shopifycall_order_count', function (req, res) {
res.send(jsonOrderCount);
//res.render('dynamic_content');
});
app.get('/shopifycall_orders', function (req, res) {
res.render('dynamic_content');
});
// Multer File Processing
app.post('/send', (req, res) => {
const output = `
<p>Please View & Accpet or Reject the PDF</p>
`;
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: '',
pass: ''
},
tls:{
rejectUnauthorized:false
}
});
// setup email data with unicode symbols
let mailOptions = {
from: '"Macwear Clothing" <shop#macwearclothing.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Order Review', // Subject line
text: 'Order Acception', // plain text body
html: output, // html body
attachments: [{'filename': 'needlesheet.pdf', 'content': req.body.needle, 'contentType': 'application/pdf'
}]
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321#example.com>
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});
console.log(req.body.needle);
});
app.get('/', (req, res) => {
res.render('index');
});
app.listen(3000, () => {
console.log('Starting MOS.......');
console.log(chalk.green('Loaded on port 3000'));
console.log('Fetching API.......');
console.log('Initial API Request will take 60 Seconds');
});
I simply used Multer to handle the uploading of the file. All that was required was to set the multer upload directory.
var upload = multer({dest: './public/uploads/'});
And then within the /send route add in upload.single('needle') and remove the arrow function:
app.post('/send', upload.single('needle'), function (req, res, next) {
});
Then within the attachments in mailOptions:
attachments: [
{
filename: req.file.originalname,
path: req.file.path
}
]
Lastly it is important to set the enctype on the HTML form to multipart/form-data otherwise the file upload via multer will not work.
you using path for both your attachment and static path so the document will not display its extension
try:
app.use(express.static('public'))

How to handle file upload using sequelize + mysql + express js?

I'm developing a simple software college project that needs pdf/doc file upload. But here comes the bottleneck: I couldn't find anywhere an example and example of this feature using the Sequelize ORM.
Has anyone done something similar using this framework?
*By the way, I know there are several npm packages for express(), but I must use sequelize.
Any advice is welcome.
Thanks in advance ;)
Configure your express app with multer. Read over the documentation for multer, but in short you store the path of the uploaded file:
const multer = require('multer')
const express = require('express')
const Sequelize = require('sequelize')
const sequelize = new Sequelize('database', 'username', 'password')
const MyModel = sequelize.define('myModel', {
filePath: Sequelize.STRING,
})
const express = express()
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './app/uploads')
},
filename: (req, file, cb) => {
cb(null, file.originalname)
}
})
app.post('/upload', multer({ storage }).single('example'), async (req, res) => {
// This needs to be done elsewhere. For this example we do it here.
await sequelize.sync()
const filePath = `${req.file.destination}/${req.file.filename}`
const myModel = await MyModel.create({ filePath })
})
A slightly simpler example (from) using AJAX.
Add to your node.js
var multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, callback) => {
console.log(req);
callback(null, './uploads');
},
filename: (req, file, callback) => {
console.log(req);
callback(null, Date.now() + file.originalname);
}
});
var upload = multer({storage:storage}).single('myFile');
app.post('/dashboard/myFile', function(req,res){
upload(req,res,function(err){
//console.log("owen",req.file,err);
if (err)
return res.end("error uploading file");
res.end("file is uploaded");
});
});
And in your HTML
<form id="myForm" name="myForm" enctype="multipart/form-data" method="post">
<input id="myFile" name="myFile" type="file">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<script>
var form = document.forms.namedItem("myForm");
form.addEventListener('submit', function(ev){
var myFile = document.getElementById('myFile').files[0];
var oData = new FormData(form);
var oReq = new XMLHttpRequest();
oReq.open("POST","/uploadFile",true);
oReq.onload = function(oEvent){
if(oReq.status == 200) {
console.log("success",oEvent);
} else {
console.log("fail",oEvent);
}
}
oReq.send(oData);
ev.preventDefault();
},false);
</script>