I have a simple app which gets heading, description and image from the user multer handle the image uploading part and I get the images in static folder called public and its sub folder uploads. Then it is toed in the database. I find it in database and try to render the image but image is not rendering. Although it is present in uploads folder but it is not rendering.
Here is My code.
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const mongoose = require("mongoose");
const multer = require("multer");
const fs = require("fs");
const path = require("path");
//APP use
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname+"./public/"));
//Multer Setup
const storage = multer.diskStorage({
destination: "./public/uploads/",
filename: (req, file, cb) => {
cb(null, file.fieldname + '_' + Date.now()+path.extname(file.originalname));
}
});
const upload = multer({ storage: storage }).single("img");
//Mongoose Setup
mongoose.connect('mongodb://localhost:27017/project-1', {useNewUrlParser: true, useUnifiedTopology: true}).then(console.log("Successfully connected to the server"));
//Routes
app.get("/", (req, res)=>{
BlogModel.find({}, function(err, foundItem){
if(err){
console.log(err);
}else{
console.log(foundItem);
res.render("home", {foundItem : foundItem});
}
})
});
app.get("/creat", (req, res)=>{
res.render("creat");
});
app.post("/creat", upload ,(req, res)=>{
const data = new BlogModel({
heading: req.body.name,
desc: req.body.desc,
img: req.file.filename
});
data.save((err)=>{
if(!err){
res.redirect("/");
}else{
console.log(err);
}
});
console.log("Successfully Submited The Form");
});
//Database Schema
const Blogschema = new mongoose.Schema({
heading: String,
desc: String,
img: String
});
//Database Model
const BlogModel = new mongoose.model("Image", Blogschema);
//Listen On Port 3000
app.listen(3000, ()=>{
console.log("Listening on port 3000");
});
<%- include('partials/header'); -%>
<% foundItem.forEach(function(item){ %>
<h1><%= item.heading %></h1>
<p><%=item.desc%></p>
<img src="./uploads/<%=item.img%>" alt="image">
<%})%>
<%- include('partials/footer'); -%>
Here it is stored in the public Folder inside Uploads
Here is the error.
Sorry if the code is to long.
Try adding 'public' for static folder name
app.use(express.static("public"));
Or if you want to use __dirname,
app.use(express.static(path.join(__dirname, 'public')))
Related
I requested data, but it's neither shows error nor data was added to database.
const express = require("express");
const { hostname } = require("os");
const path = require("path")
const bodyparser = require("body-parser")
const mongoose = require('mongoose');
main().catch(err => console.log(err));
async function main() {
await mongoose.connect('mongodb://localhost/contactdance');
}
const app = express()
const port = 80;
//Defining mongoose scheme
const contactSchema = new mongoose.Schema({
name: String,
phone: String,
email: String,
address: String,
desc: String
});
const Contact = mongoose.model('Contact', contactSchema);
// EXPRESS SPECIFIC STUFF
app.use('/static', express.static('static')) // For serving static files
app.use(express.urlencoded())
// PUG SPECIFIC STUFF
app.set('view engine', 'pug') // Set the template engine as pug
app.set('views', path.join(__dirname, 'view')) // Set the views directory
//end point
app.get('/', (req, res)=>{
const params ={ }
res.status(200).render('home.pug', params);
})
app.get('/contact', (req, res)=>{
const params ={ }
res.status(200).render('contact.pug', params);
})
app.post('/contact', (req, res)=>{
var myData = new Contact(req.body);
myData.save().then(()=>{
res.send("This item has been saved to the database")
}).catch(()=>{
res.status(400).send("item was not saved to the databse")
})
})
app.listen(port, ()=>{
console.log(`The application started successfully on port ${port}`);
});
i expected to see text whether it succeeded or not but it didnt happen neither data was added.It didnt showed me error and i am like WTF.when i sew collections database contact was added but not data inside of it.
I'm new to NODE JS and practicing with some POST forms from PUG to a NODE JS server.
I have a simple form to update a photo title and description posted onto mongodb. When I submit the form from the web browser the submission input comes back to the server as 'undefined'.
These two processes in POST log 'undefined': (see below with more full code)
console.log("title:", req.body.title)
console.log("description", req.body.description)
I've tried to use PUT instead. Weirdly I've done this before and it's worked. So I'm not sure what the issue is...
router handling the POST request:
//users.js
const express = require('express');
const router = express.Router();
const app = express();
const multer = require('multer');
const photoController = require('../controllers/photoController');
const flash = require('express-flash');
const Photo = require('../models/photoModel');
const upload = multer({
storage: photoController.storage,
fileFilter: photoController.imageFilter
});
// flash messaging
router.use(flash());
router.get('/', (req, res, next)=>{
Photo.find({})
.then((photos)=>{
res.render('photos', {
photos : photos,
flashMsg: req.flash("fileUploadError")
});
})
.catch((err)=>{
if (err) {
res.end("ERROR!");
}
});
});
router.get('/:photoid', (req, res, next)=>{
console.log("finding "+req.params.photoid);
Photo.findOne({'_id': req.params.photoid})
.then((photo)=>{
res.render('updatePhoto', {
photo: photo,
flashMsg: req.flash("photoFindError")
});
}).catch((err)=>{
if (err) console.log(err);
});
});
// I think the error is below!!
router.post('/:photoid', (req, res, next)=>{
console.log("title:", req.body.title)
console.log("description", req.body.description)
Photo.findOne({'_id': req.params.photoid})
.then((photo)=>{
var data = {
title: req.body.title,
description: req.body.description
}
photo.set(data);
photo.save().then(()=>{
res.redirect('/photos');
});
})
.catch((err)=>{
if (err) console.log(err);
});
});
PUG form:
.row
.col-md-6.col-md-offset-3
if flashMsg.length > 0
.alert.alert-danger <strong>FLASH!</strong>#{flashMsg}
p Title: #{photo.title}
p Description: #{photo.description}
p Size: #{photo.size} | Filename: #{photo.originalname} | Uploaded: #{photo.createdAt}| Modified: #{photo.updatedAt}
img(src=photo.imageurl, width="250")
form(method='POST' action="/photos/"+photo._id enctype="multipart/form-data")
div.form-group
label(for='name') Photo Title :
input#name.form-control(type='text', value=photo.title name='title')
div.form-group
label(for='email') Description:
input#email.form-control(type='text', value=photo.description name='description')
div.form-group
label(for='image') Image:
input#name.form-control(type='hidden', name='_id' value=photo._id)
button.btn.btn-primary(type='submit') Update Your Photo
Thanks for your help
You should add to your code the app.use(express.json()) middleware in order to parse automatically the req.body from your request.
const express = require('express');
const router = express.Router();
const app = express();
app.use(express.json()); // Here
const multer = require('multer');
const photoController = require('../controllers/photoController');
const flash = require('express-flash');
const Photo = require('../models/photoModel');
const upload = multer({
storage: photoController.storage,
fileFilter: photoController.imageFilter
});
I am using Multer Node JS package to upload files to my app sever , the code is basically typical upload file code
const express = require('express')
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
const app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
// req.files is array of `photos` files
// req.body will contain the text fields, if there were any
})
But each time a file is being uploaded the Node server becomes unresponsive and frontend from other request doesnt receive any response from other APIs until the file is uploaded.
Whats the best way to tackle this ?
In your sample code, you must just send a response to the client by res.json() or res.end() :
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const app = express();
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
res.status(204).end();
});
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
// req.files is array of `photos` files
// req.body will contain the text fields, if there were any
res.status(204).end();
});
i can give you an example of how i implemented an imageupload in my app. it the code to upload a profile image for a user. i am also using multer middleware so it shoulder be similiar for you:
code is as follows:
// multer middleware:
const multer = require('multer');
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpg',
'image/jpg': 'jpg',
};
module.exports = storage = multer.diskStorage({
destination: (req, file, cb) => {
const isValid = MIME_TYPE_MAP[file.mimetype];
let error = new Error('invalid mime type');
if (isValid) {
error = null;
}
cb(error, 'images');
},
filename: (req, file, cb) => {
const name = file.originalname.toLowerCase().split(' ').join('-');
const ext = MIME_TYPE_MAP[file.mimetype];
if (name.includes('.' + ext)) {
cb(null, name)
} else {
cb(null, name + '.' + ext);
}
},
});
and here the code in the service handling the fileupload
// profile service in backend written in express
exports.uploadImage = (req, res, next) => {
const url = req.protocol + '://' + req.get('host');
profileRepository
.findOne({ _id: req.params.id })
.then((response) => {
const fetchedUser = response;
fetchedUser.imagePath = url + '/images/' + req.file.filename;
profileRepository
.updateOne({ _id: req.params.id }, fetchedUser)
.then((response) => {
return res.status(200).json({
message: 'profileimage updated',
});
})
.catch((error) => {
return res.status(500).json({
message: 'uploading image failed',
});
});
})
.catch((error) => {
return res.status(404).json({
message: 'fetching user failed',
});
});
};
then i use the middleware in my profile routes file like this:
// profile.routes.js
const express = require('express');
const ProfileController = require('./profileController');
const checkAuth = require('../middleware/checkAuth');
const router = express.Router();
const fileStorage = require('../middleware/fileStorage');
const multer = require('multer');
// imageUpload
router.post('/user/image/:id', checkAuth, multer({storage: fileStorage}).single('image'), ProfileController.image);
my Controller then calls the service function with the actual business logic like this:
// profile.controller.js
const profileService = require('./profileService');
exports.image = (req, res, next) => {
return profileService.uploadImage(req, res);
};
and finally my route is used by my app.js file like this:
// app.js
const express = require('express');
const profileRoutes = require('./profile/profileRoutes');
const app = express();
// set images path for saving images on server
app.use('/images', express.static(path.join('images')));
app.use('/api', profileRoutes);
module.exports = app;
i hope i was able to point you in the right direction with my example
I tried all possible scenarios and I tried with multiple variations and approaches suggested by documentation and by other stackoverflow questions.
Any of them worked -> I keep getting req.file is: undefined
Form:
<form action="/send" enctype="multipart/form-data" method="POST">
<input type="file" id="file" name="file">
<button type="submit">Submit</button>
Express Setup:
const express = require('express');
const ejs = require('ejs');
const homeController = require('./controlers/homeController');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.listen(3000);
/* routes */
app.use(homeController);
I have the following code:
var multer = require('multer')
const storage = multer.diskStorage({
destination: './public/data/uploads',
filename: function(req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
var upload = multer({
storage: storage
}).single('file');
router.get('/', (req, res) => {
res.render('home')
})
router.post('/send', (req, res) => {
upload(req, res, (err) => {
if (err) console.log(err);
console.log('req.file is: ' + req.file);
});
})
I spent 2 days trying to figure this out but I can't see the light at the end of the tunnel, and i just want to get the file from client and send it with nodemailer as attachement later on.
Answer obtained based on eMAD suggestion on question How to perform an HTTP file upload using express on Cloud Functions for Firebase (multer, busboy)
Solution below:
File is saved on the storage location you define in muller.
req.files is an array with the details of the file/files you upload.
PS: thanks #eol for pointing me in this direction
const contactControler = require('../controlers/contactController');
const busboy = require('busboy')
const express = require('express');
const router = express.Router();
var multer = require('multer');
const SIZE_LIMIT = 10 * 1024 * 1024 // 10MB
var stor = multer.diskStorage({
destination: '../public/cv',
filename: function(req, file, callback) {
callback(null, file.originalname);
}
});
const multipartFormDataParser = multer({
storage: stor,
// increase size limit if needed
limits: { fieldSize: SIZE_LIMIT },
// support firebase cloud functions
// the multipart form-data request object is pre-processed by the cloud functions
// currently the `multer` library doesn't natively support this behaviour
// as such, a custom fork is maintained to enable this by adding `startProcessing`
// https://github.com/emadalam/multer
startProcessing(req, busboy) {
req.rawBody ? busboy.end(req.rawBody) : req.pipe(busboy)
},
})
router.post('/send', multipartFormDataParser.any(), contactControler.send);
Please try adding upload in your route as middleware.
router.post('/send', upload, (req, res) => { ...
I have uploaded the image in to a local directory using Busboy and passed
the path of the image to the MongoDB using Mongoose but now I unable to
retrieve the path
to display the image in my ejs view. I'm new to this nodejs. Please help me
to display the image.
Thank you Very much in Advance :)
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
var nameSchema = mongoose.Schema({
newfile: Object,
path: String
});
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
app.route('/')
.post(function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
//mongo save
var paths = new compileSchema({newfile : dirname, passReqToCallback: true});
paths.save(function(err){
if(err) throw err;
compileSchema.find({newfile: dirname}, (err, result) =>{
console.log();
return result;
});
});
fstream.on('close', function () {
console.log("Upload Finished of " + filename);
//where to go next
res.redirect('/profile');
});
});
});
app.get('/profile', (req, res)=>{
res.render('profile',{photo: req.result});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
My Ejs file is :
<img src='<%= photo.newfile %>' >
This is the typical process of writing and reading from Mongodb using Mongoose. I have not checked whether your streaming and other things work fine but the db workflow would be better this way.
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
//You can import your schema like this
const Name = require('./name');
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
//I have changed your route since it seems to be clashing with the above
app.post('/save' ,function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
//mongo save
fstream.on('close', function () {
//You can either save to mongodb after streaming closes or while it is streaming but in this case I will do it after.
console.log("Upload Finished of " + filename);
//where to go next
//Declare your schema object here
let name = new Name({
newfile:'Whatever you want to store here',
path: path
});
//Save your declared schema like this
name.save((err) => {
if(err) throw err;
console.log(`saved : ${name}`);
//When you redirect here, it will go to /profile route
res.redirect('/profile');
});
});
});
});
app.get('/profile', (req, res)=>{
//You must retrieve from mongodb your object here if this is where you want the object to be
//{} empty query will find all objects in the table
Name.find({}, (err, result) => {
if(err) throw err;
//after everything was found, send it to front end
res.render('profile',{
photo: req.result,
//Now your 'compileSchema' object is available at front end as 'result' object
result:result
});
});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
name.js (create one schema js file for each table you will be working with)
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let compileSchema = new Schema({
newfile: Object,
path: String
});
let Compile = mongoose.model('Compiles', compileSchema);
module.exports = Compile;
Check first that you are receiving and streaming file correctly. If you are, it must work fine. Also, I don't know why you want to save a newfile:object field but all you really need to do is save the path to the image file then retrieve it where you need to use the image and use the path as the <img src='path'> Refer to the comments.