Maybe this is an already answered question but I can't seem to find the right answer for me. I can't see what's wrong with my code.
I have a form to upload the specifics of a vehicle such as route, price, a picture of the vehicle, etc. When I get the url of the image, it doesn't display anything
example image
Here's the code I use to post my form
//POST create vehicle
app.post('/createVehicle', async function(req, res, next){
const fileData = new Parse.File("VehiclePic", { base64: req.body.VehicleImg }, "image/png");
console.log(fileData);
let car = new Car();
const Vehicle = {
VehicleImg: fileData,
Name: req.body.Name,
description: req.body.description,
Price: parseInt(req.body.Price),
Route: req.body.Route,
PassengerAmount: parseInt(req.body.PassengerAmount)
}
try{
fileData.save().then(saved => {
car.set('Image', saved);
car.set('Name', Vehicle.Name);
car.set('Description', Vehicle.description);
car.set('Route', Vehicle.Route);
car.set('Price', Vehicle.Price);
car.set('PassengerAmount', Vehicle.PassengerAmount);
console.log("URL vehiculo " + saved.url());
car.save();
console.log("El vehiculo ha sido creado con exito!");
})
}catch(error){
console.error('error ' , error);
}
res.redirect('/');
});
The reason I don't use Vehicle.VehicleImg is because it returns me an undefined object.
Here's the code to get all data
const Car = Parse.Object.extend('Vehicle');
const query = new Parse.Query(Car);
app.get('/', async function(req, res) {
const VehicleInfo = [];
query.notEqualTo("objectId", null);
try {
const result = await query.find();
result.forEach(vehicle => {
const vehiclePic = vehicle.get('Image');
VehicleInfo.push({
VehicleID: vehicle.id,
VehicleImage: vehiclePic,
VehicleName: vehicle.get('Name'),
Description: vehicle.get('Description'),
Price: vehicle.get('Price'),
Rating: vehicle.get('Rating'),
Route: vehicle.get('Route'),
PassengerAmount: vehicle.get('PassengerAmount')
});
});
res.render('index', {
title: 'MainPage',
VehicleData: VehicleInfo
});
} catch (error) {
console.error('error fetching objects', error);
}
});
EDIT:this is the form, I'm using ejs.
<div class="createVehicle-section container">
<br>
<form method="POST" action="/createVehicle" enctype="multipart/form-data">
<div id="img">
<label for="VehicleImg">Seleccione la imagen:</label>
<input type="file" id="VehicleImg" name="VehicleImg" >
</div>
<br>
<div class="col-lg-12 row">
<div class="col-md-6">
<label for="VehicleName">Nombre del vehiculo</label>
<input type="text" id="VehicleName" name="Name">
<br>
<label for="DescriptionVe">Descripción</label>
<input type="text" id="Descriptionve" name="description">
</div>
<div class="col-md-6">
<label for="PriceVe">Precio</label>
<input type="number" id="PriceVe" name="Price" min="0" max="9999">
<br>
<label for="RouteVe">Ruta</label>
<input type="text" id="RouteVe" name="Route">
</div>
</div>
<br>
<div class="col-md-6 container">
<label for="PassegerAmountVe">Cantidad de Pasajeros Permitida</label>
<input type="number" id="PassengerAmountVe" name="PassengerAmount" min="0" max="9999">
</div>
<br>
<div class="text-center">
<input class="btn btn-main btn-lg btn-shadow" type="submit" value="Guardar"/>
</div>
</form>
<br>
</div>
EDIT: Here's my multer code to upload it to a localstorage, and I need to upload it to back4app.
//Multer Image Storage
const storage = multer.diskStorage({
destination: './public/images/',
filename: function(req, file, cb){ //cb = callback
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
// Init Upload
const upload = multer({
storage: storage,
limits:{fieldSize: 1000000},
fileFilter: function(req, file, cb){
checkFileType(file, cb);
}
}).single('VehicleImg');
Try the following code:
const upload = multer();
app.post('/createVehicle', upload.single('VehicleImg'), async function(req, res, next){
const fileData = new Parse.File("VehiclePic.png", [...req.file.buffer], "image/png");
console.log(fileData);
let car = new Car();
const Vehicle = {
VehicleImg: fileData,
Name: req.body.Name,
description: req.body.description,
Price: parseInt(req.body.Price),
Route: req.body.Route,
PassengerAmount: parseInt(req.body.PassengerAmount)
}
try{
fileData.save().then(saved => {
car.set('Image', saved);
car.set('Name', Vehicle.Name);
car.set('Description', Vehicle.description);
car.set('Route', Vehicle.Route);
car.set('Price', Vehicle.Price);
car.set('PassengerAmount', Vehicle.PassengerAmount);
console.log("URL vehiculo " + saved.url());
car.save();
console.log("El vehiculo ha sido creado con exito!");
})
}catch(error){
console.error('error ' , error);
}
res.redirect('/');
});
Related
I'm developing an application with Node.js and EJS but there is an error. It says "msg_type is not defined". When I'm using handlebars, there is no problem. What is my mistake. Actually, when url goes to /auth/login , the message is displaying but it's not displaying in /login routing.
my users.js file (controllers)
exports.login = async (req, res,next) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).render("login", {
msg: "Kullanıcı Adınız veya Parolanız Hatalı",
msg_type: "error",
},
next()
);
}
await login_db.query(
"select * from users where email=?",
[email],
async (error, result) => {
console.log(result);
if (result.length <= 0) {
return res.status(401).render("login", {
msg: "E-mailiniz veya Parolanız Hatalı",
msg_type: "error",
});
} else {
if (!(await bcrypt.compare(password, result[0].PASS))) {
return res.status(401).render("login", {
msg: "E-mailiniz veya Parolanız Hatalı",
msg_type: "error",
});
} else {
const id = result[0].ID;
const token = jwt.sign({ id: id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN,
});
console.log("The Token is " + token);
const cookieOptions = {
expires: new Date(
Date.now() +
process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true,
};
res.cookie("joes", token, cookieOptions);
res.status(200).redirect("/anasayfa");
}
}
}
);
} catch (error) {
console.log(error);
}
};
my auth.js file
const express = require("express");
const userController = require("../controllers/users");
const router = express.Router();
router.post("/login", userController.login);
my login.ejs file
<% if (true) { %>
<p class="<%= msg_type %>"><%= msg %> </p>
<% } %>
<form action="/auth/login" method="post">
<div class="data">
<label for="email">Email</label>
<input type="email" name="email" id="email" />
</div>
<div class="data">
<label for="password">Şifre</label>
<input type="password" name="password" id="password" />
</div>
<div class="forgot-pass">
Şifrenizi mi unuttunuz?
</div>
<div class="btn">
<button type="submit">Giriş Yap</button>
</div>
<div class="signup-link">
Kayıtlı değil misin? Şimdi Kayıt Ol!
</div>
</form>
my app.js file
app.use("/", require("./routes/pages"));
app.use("/auth", require("./routes/auth"))
;
my pages.js file
router.get(["/", "/login"], (req, res) => {
//res.send("<h1>Hello Tutor Joes Salem</h1>");
res.render("login");
});
The variable should be exported from the original file(users.js) and also should be imported in login.ejs, so you can use it without problems, this is how things work in Javascript.
I'm trying to create a simple form which can upload file(pdf & image) and texts together using Node.js. Nonetheless, I don't wanna save the pdf file to MySql database, rather I want it to be kept in my internal storage "./uploads" folder. I have used npm formidable, mv, and multer, yet nothing works, anybody knows why?
Here's my html form
<form action="/auth/registerEvent" method = "POST">
<h5> Enter Your Event Information</h5>
<div class="form-group">
<label for="eventName">Event Name</label>
<input type="text" class="form-control" id="eventName" name="eventName" placeholder="Event Name">
</div>
<div class="form-group">
<label for="eventDescription">Description</label>
<textarea class="form-control" id="eventDescription" name="eventDescription" placeholder="Event Description: No more than 200 words" rows="3"></textarea>
</div>
<div class="form-group">
<label for="eventPoster">Poster</label>
<input type="file" class="form-control" id="eventPoster" name="eventPoster" enctype="multipart/form-data" accept=".jpg, .png, .jpeg">
</div>
<div class="form-group">
<label for="eventProposal">Sponsor Proposal</label>
<input type="file" class="form-control" id="eventProposal" name="eventProposal" enctype="multipart/form-data" accept=".pdf">
</div>
<br>
<button type="submit">Submit</button>
</form>
This is my app.js
const express = require('express');
const path = require('path');
const app = express();
const mysql = require('mysql');
const dotenv = require('dotenv');
dotenv.config({path: './.env'}); // connect to .env
// set views folder
app.set('view engine', 'html');
app.engine('html', require('hbs').__express);
// set the directory to css and js
const publicDirectory = path.join(__dirname, './public');
app.use(express.static(publicDirectory));
// Parse URL encoded bodies (as sent by HTML Form)
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
// Define routes
app.use('/', require('./router/pages.js'));
app.use('/auth', require('./router/auth.js'));
// connect to mysql
const db = mysql.createConnection({
host: process.env.LOCALHOST,
user: process.env.USER,
password: process.env.PASSWORD,
database: process.env.DATABASE,
});
db.connect( (err) => {
if (err) console.log(err);
else console.log('Database is connected');
} )
// laptop server
app.listen(3000, (req, res)=>{
console.log('Server is running at localhost:3000');
});
and finally the "auth.js"
const formidable = require('formidable');
const fs = require('fs');
const mysql = require('mysql');
const db = mysql.createConnection({
host: process.env.LOCALHOST,
user: process.env.USER,
password: process.env.PASSWORD,
database: process.env.DATABASE,
});
exports.registerEvent = (req, res) => {
const {
eventName, eventInstitution,
// eventStartDate, eventEndDate,
eventAddress, eventDescription,
eventPoster, eventProposal,
// eoName, eoPhone, eoEmail
} = req.body;
if (req.url === "/registerEvent") {
const form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
const oldPath = eventPoster.path;
const newPath = './uploads' + eventPoster;
fs.rename(oldPath, newPath, function (err) {
if (err) throw err;
});
})
}
// db start
db.query('INSERT INTO registerevent SET ? ', {
EventName: eventName,
Institution: eventInstitution,
// StartDate: eventStartDate,
// EndDate: eventEndDate,
Address: eventAddress,
Description: eventDescription,
// Poster: eventPoster,
// Proposal: eventProposal,
// ContactName: eoName,
// PhoneNumber: eoPhone,
// Email: eoEmail,
}, (error, result) => {
if (error) { console.log(error); }
else {
res.statusCode = 302;
res.setHeader("Location", "/feedback");
res.end();
}
});
// db end
}
So when the customer enters the name & address it goes to sql, and the poster and proposal files will be sent to my "/uploads" directory. Please help
When I'm sending data in my Node.js application as raw JSON/x-www-form-urlencoded from postman it's getting passed but when sending the data as form-data from postman or from my angular frontend, req.body is coming as undefined. I'm using body-parser on my index.js of my Node.js application.
app.post(`${baseUrl}/post-news`, (req, res) => {
CategoryModel.findOne(
{ categoryId: req.body.category },
(err, result) => {
if (err) {
console.log("Error at finding category ::", err);
res.send(err);
}
if (result) {
let newArticle = new ArticleModel({
categoryName: result.categoryName,
categoryId: result.categoryId,
imagePath: req.file && req.file.path
});
newArticle.save((err, result) => {
if (err) {
console.log("Error at saving new news ::", err);
res.send(err);
} else {
console.log("Successfully saved new news");
res.send(result);
}
});
} else {
console.log("No category found for ::", req.body.category);
res.send("No category found");
}
}
);
});
index.js
app.use(bodyParser.urlencoded({ limit: "10mb", extended: true }));
app.use(bodyParser.json({ limit: "10mb" }));
HTML:
<form fxLayout="row wrap" [formGroup]="createNewsForm" (ngSubmit)="createNews()"
enctype="multipart/form-data">
<div fxFlex="100" fxFlex.gt-sm="100" class="px-1" ngClass.sm="mt-1" ngClass.xs="mt-1">
<label>Title</label>
<mat-form-field class="w-100 form-group">
<input type="text" matInput placeholder="Article title (required)"
formControlName="articleTitle" name="articleTitle" required>
<mat-error *ngIf="articleTitle?.invalid">Please enter a valid Title</mat-error>
</mat-form-field>
</div>
<div fxFlex="100" fxFlex.gt-sm="100" class="px-1" ngClass.sm="mt-1" ngClass.xs="mt-1">
<label>Category</label>
<mat-form-field class="w-100 form-group">
<select matNativeControl formControlName="articleCategory" name="articleCategory"
color="accent">
<option *ngFor="let category of categories" [value]="category.categoryId">
{{category.categorySlug}}</option>
</select>
</mat-form-field>
</div>
<div class="button-wrap" fxFlex="100" fxFlex.gt-sm="100" class="px-1" ngClass.sm="mt-1"
ngClass.xs="mt-1">
<button class="btn-project" mat-raised-button color="accent" type="submit">Post News</button>
</div>
</form>
component.ts
createNewsForm: FormGroup;
ngOnInIt() {
this.createNewsForm = this.formBuilder.group({
articleTitle: ['', Validators.required],
articleCategory: ['', Validators.required],
imagePath: ['', Validators.required]
})
}
public createNews: any = () => {
const formData = new FormData();
formData.append('imagePath', this.createNewsForm.get('imagePath').value);
formData.append('title', this.createNewsForm.get('articleTitle').value);
formData.append('category', this.createNewsForm.get('articleCategory').value);
this.appService.createNews(formData).subscribe(
data => {
console.log(data)
},
error => {
console.log(error);
})
}
appService.ts
import { HttpClient } from '#angular/common/http';
public createNews = (formData) => {
let myResponse = this.http.post(this.baseUrl + '/api/v1/post-news', formData);
return myResponse;
}
You need an appropriate parser to handle multipart/form-data (this is what the content-type will be set to after selecting "form-data" in postman), the built in bodyParsers(urlencoded/json) do not handle it. One popular package you can use is multer.
They provide an upload-middleware that you can plug into your route handler, e.g.:
const upload = multer({ dest: 'uploads/' })
app.post(`${baseUrl}/post-news`, upload.single('file'), (req, res) => {
// req.file will now hold the uploaded file
// req.body will hold the text fields of the form
});
I am building a MEAN Shop App, trying to store the product image in mongodb but some error is coming
typeError: cannot read the property 'productimage' of undefined
This is the route function for adding product
function addProduct(req, res, next){
var newProduct = new Product({
productName: req.body.productname,
productCategory: req.body.productcategory,
productDescription: req.body.productdescription,
productPrice: req.body.productprice
});
newProduct.productImage.data = fs.readFileSync(req.file.productimage);
newProduct.productImage.contentType = 'jpg';
newProduct.save(function(err){
if(err){
console.log("error saving product");
res.status(400).json({
success: false,
message:'Error processing request '+ err});
}
else{
console.log("product inserted");
res.status(201).json({
success: true,
message: 'Product added successfully.'
});
}
});
}
module.exports = {addProduct);
This is the product model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const productSchema = new Schema({
productname : { type: String },
productCategory: { type: String },
productDescription: { type: String },
productImage: { data: Buffer, contentType: String },
productPrice: { type: Number }
});
module.exports = mongoose.model('product', productSchema, 'products');
This is the html file
<form class="form-style-9"
[formGroup]="productForm"
(ngSubmit)="addProduct(productForm.value)"
enctype="multipart/form-data"
>
<ul>
<li><span>Product Name</span>
<input type="text" name="productname" class="field-style field-full align-none" placeholder="Name" formControlName="productname" />
</li>
<span>Product Category</span><br>
<select formControlName="productcategory">
<option value="Clothing">Clothing</option>
<option value="Electronics">Electronics</option>
<option value="Books">Books</option>
<option value="Toys">Toys</option>
</select>
<li><span>Product Description</span>
<textarea name="productdescription" class="field-style" placeholder="Product Description" formControlName="productdescription"></textarea>
</li>
<li><span>Product Image</span>
<input type="file" name="productimage" class="field-style field-full align-none" placeholder="Image" formControlName="productimage"/>
</li>
<li><span>Product Price</span>
<input type="number" name="productprice" class="field-style field-full align-none" placeholder="Product Price" formControlName="productprice" />
</li>
<li>
<input type="submit" value="Add Product" />
</li>
</ul>
</form>
this is component file
export class ProductComponent implements OnInit {
constructor(private fb: FormBuilder,
private router: Router,
private productService: ProductService,
private toastr: ToastrService) { }
ngOnInit() {
}
productName = new FormControl("");
productCategory = new FormControl("");
productDescription = new FormControl("");
productImage = new FormControl("");
productPrice = new FormControl("");
productForm: FormGroup = this.fb.group({
'productname': this.productName,
'productcategory': this.productCategory,
'productdescription': this.productDescription,
'productimage': this.productImage,
'productprice': this.productPrice,
});
addProduct(formdata:any) {
this.productService.addProduct(this.productForm.value)
.subscribe(data => {
if (data.success === false) {
this.toastr.error(data.message);
} else {
this.toastr.success(data.message);
this.router.navigate([' ']);
}
this.productForm.reset();
});
}
}
I tried using multer but i dont think its working or may be i am coding it wrong. Please correct me what am i doing wrong.
I had created a different folder for storing image server/public/images, this is the same folder that contains routes and models server/models/ and server/routes/.
This is the server file.
var multer = require('multer');
var app = express();
var api = require('./server/routes/api');
var image = multer({ dest:'./server/public/' });
app.post('/product', image.single('images'), api.addProduct);
What am i doing wrong here?
I think there is a problem with your multer configuration.
Can you share your require's and multer middleware as well.
Also I have included a sample configuration below to configure your multer middleware.
const multer = require('multer')
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './path/to/file')
},
filename: (req, file, cb) => {
cb(null, "PDFS-"+file.originalname.substring(0, file.originalname.lastIndexOf('.')) + '-' + Date.now()+(path.extname(file.originalname)).toLowerCase())
}
});
var upload = multer({
storage: storage,
fileFilter: function (req, file, callback) {
var ext = (path.extname(file.originalname)).toLowerCase();
if(ext !== '.pdf') {
return callback(new Error('Only pdf format files are allowed!'))
}
callback(null, true)
},
limits:{
fileSize: 1024*1024
}
});
app.post('/upload', function(req, res, next){
upload.single('productimage')(req, res, function (err) {
if (err) {
console.log("upload err"+err);
res.render('upload');
return;
}
else{
if (req.file===undefined) {
console.log("empty");
res.render('upload');
}
else{
console.log("done");
res.render('upload');
}
}
});
});
i'm building a web page for a library with node and mongoose in atom. I've created a log in form, register and an "add book". Now in the home page i want to see all the books and i dont know to to do that. I know it way have something to do with double {{}} or triple {{{}}} brackets but I'm not sure. I will put it later in a prettyer form, for now i just want to see how I can print, for example the titles. Btw i'm using the handlebars view engine.
<h2 class="page-header">Cartile existente</h2>
<h4>In curand!</h4> // <- there I'm supposed to put the book titles.
<h2 class="page-header">Adauga o carte noua</h2>//this is the "add a book"
{{#if errors}}
{{#each errors}}
<div class="alert alert-danger">{{msg}}</div>
{{/each}}
{{/if}}
<form method="post" action="/booksImp/addbook">
<div class="form-group">
<label>Numar Inventar</label>
<input type="text" class="form-control" placeholder="Numar curent" name="nrinv">
</div>
<div class="form-group">
<label>Titlu</label>
<input type="text" class="form-control" placeholder="Titlu" name="titlu">
</div>
<div class="form-group">
<label>Autor</label>
<input type="text" class="form-control" placeholder="Autor" name="autor">
</div>
<div class="form-group">
<label>Editura</label>
<input type="text" class="form-control" placeholder="Editura, Locul publicatiei" name="editura">
</div>
<div class="form-group">
<label>An</label>
<input type="text" class="form-control" placeholder="An publicatie" name="an">
</div>
<div class="form-group">
<label>Pret</label>
<input type="text" class="form-control" placeholder="Pret" name="pret">
</div>
<button type="submit" class="btn btn-success">Trimite</button>
</form>
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var BookSchema = mongoose.Schema({
nrinv: {
type: String,
index: true
},
titlu: {
type: String
},
autor: {
type: String
},
editura: {
type: String
},
an: {
type: String
},
pret: {
type: String
}
});
var Book = module.exports = mongoose.model('bookImp', BookSchema);
module.exports.getBooks = (callback, limit) => {
Book.find(callback).limit(limit);
}
module.exports.getBookById = (id, callback) => {
Book.findById(id, callback);
}
module.exports.addBook = (book, callback) => {
Book.create(book, callback);
}
module.exports.removeBook = (id, callback) => {
var query = {
_id: id
};
BookImp.remove(query, callback);
}
var express = require('express'); //this is the controller code =))))
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var Book = require('../models/bookImp');
router.get('/addbook', ensureAuthenticated, function(req, res, next) {
res.render('addbook');
});
router.post('/addbook', function(req, res, next) {
var nrinv = req.body.nrinv;
var titlu = req.body.titlu;
var autor = req.body.autor;
var editura = req.body.editura;
var an = req.body.an;
var pret = req.body.pret;
//console.log(name);
req.checkBody('nrinv', 'Introduceti numarul de inventar').notEmpty();
req.checkBody('titlu', 'Introduceti titlul').notEmpty();
req.checkBody('autor', 'Introduceti autorul').notEmpty();
req.checkBody('editura', 'Introduceti editura si locul').notEmpty();
req.checkBody('an', 'Introduceti anul').notEmpty();
// req.checkBody('an', 'Introduceti anul').isnumber();
req.checkBody('pret', 'Introduceti pretul').notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('addbook', {
errors: errors
});
} else {
var newBook = new Book({
nrinv: nrinv,
titlu: titlu,
autor: autor,
editura: editura,
an: an,
pret: pret
});
Book.addBook(newBook, function(err, book) {
if (err) throw err;
console.log(book);
});
req.flash('success_msg', 'Ati adaugat o carte cu succes');
res.redirect('/booksImp/addbook');
}
});
router.post('/addbook',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/booksImp/addbook',
failureFlash: true
}),
function(req, res) {
res.redirect('/');
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
//req.flash('error_msg', 'Trebuie sa va logati');
res.redirect('/users/login');
}
}
module.exports = router;
var express = require('express');
var router = express.Router();
var Book = require('../models/bookImp');
router.get('/', ensureAuthenticated, function(req, res, next) {
res.render('index');
});
router.get('/api/books', ensureAuthenticated, function(req, res) {
Book.getBooks(function(err, books) {
if (err) {
throw err;
}
res.json(books);
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
//req.flash('error_msg', 'Trebuie sa va logati');
res.redirect('/users/login');
}
}
module.exports = router;