Upload and retrieve image using parse and back4app with nodejs and express - javascript

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

Why a variable is not defined in EJS

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 can't upload PDF file in node.js

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

req.body returning undefined when sending data as form-data

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
});

Mean Stack: How can I store image in mongodb with nodejs expressjs and angular 6?

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');
}
}
});
});

Read data from mongoose with node in Atom

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;

Categories

Resources