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.
Related
const { timeStamp, time } = require('console');
const express = require('express');
const fileUpload = require('express-fileupload');
const path = require("path");
const util = require('util');
const app = express();
const port = 3000;
app.use(express.json());
app.use(express.static('public'))
app.use('/css', express.static(__dirname + 'public/css'))
app.use('/images', express.static(__dirname + 'public/images'))
app.use('/js', express.static(__dirname + 'public/js'))
app.use(express.urlencoded({ extended: true }));
app.use(fileUpload());
app.use(express.static("./public"));
app.post("/upload", async (req, res) => {
try {
// File name, size and type values
const file = req.files.file;
const fileName = file.name;
const size = file.data.length;
const extension = path.extname(fileName);
const name = file;
// Allowed filetypes
const allowedExtensions = /png|jpg|dds|ico|mov|mp4|flv|avchd|avi|webm|mp3|aac|wav|flac|svg|webp|gif|bmp|tiff|psd|psb|blend|fbx|obj|raw|aep|prel|prproj|ai/;
// Mazimun file Size
if (!allowedExtensions.test(extension)) throw "Filetype not allowed"
if (size > 200000000) throw "File must be less than 200MB"
// Uploaded file name
const md5 = file.md5;
const URL = "/uploads/" + fileName + Date.now() + extension;
await util.promisify(file.mv)("./public" + URL);
// Errors and Success messages
res.json ({
message: "File uploaded successfully!",
url: URL,
})
} catch(err){
console.log(err);
res.status(500).json({
message: err,
})
}
})
app.listen(port, () => console.info(`Listening on port ${port}`))
So I have this script for uploading images to a folder in my public folder in the root directory of my website, I'm a real noob when it comes to js so, I was wondering how do I implement a button that let's the user select a file as well as a submit button and maybe perhaps a couple of text fields where the user can add info about the file in the frontend so it works in the backend?
Because I have no idea of how to make the frontend and backend work together in such a way.
Thanks for any help
I am new to Node JS, so things are not coming easy to me. The scenario is I have input field which will accept multiple files.
<input id="upload-input" type="file" name="uploads[]" multiple="multiple">
in my JS script I grab the the change event of this field, and create a post request to my uploader app which is running in different port using formData and ajax post method
$('#upload-input').on('change', function() {
var files = $(this).get(0).files;
if (files.length > 0) {
var formData = new FormData();
formData.append('directory', "path/to/directory");
for (var i = 0; i < files.length; i++) {
var file = files[i];
formData.append('uploads[]', file, file.name);
}
$.ajax({
url: 'https://myurl.com:3000/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
console.log(data);
},
});
}
});
Now the file is sending and in my backend I can upload that using formidable, but the problem is I cannot get the directory value, Here is my code
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
app.set('views', __dirname + '/public');
app.use('/uploads', express.static(process.env.USER_UPLOADS))
var cors=require('cors');
app.use(cors({origin:true,credentials: true}));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
I tried
console.log(req.body)
but it returns undefined, So how can I get the directory value from my backend?
Thanks in advance.
To fix your issue, I made some changes to your main app's server file
i.e. server.js/app.js/index.js anyone that applies to you. See changes below:
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var bodyParser = require('body-parser');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
var cors=require('cors');
app.set('views', __dirname + '/public');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors({ origin:true, credentials: true }));
app.use('/uploads', express.static(process.env.USER_UPLOADS));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
// Note the changes here
form.parse(req, (error, fields, files) => {
console.log(JSON.stringify({
fields, // { directory: "path/to/directory" }
files // contains the uploaded files
}), null, 2);
});
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
According to the docs at here, form.parse can take an optional callback function.
Parses an incoming node.js request containing form data. If cb is provided, all fields and files are collected and passed to the callback:
form.parse(req, function(err, fields, files) {
// ...
});
I am trying to send multiple video files with express and mediaserver.
Is there a way to check if a file has finished streaming and then change the video to the next one?
Below is the express request.
So to clarify I can send a video over with the below request but I do not know how to change the file once it has finished streaming, I read that mediaserver is great at sending media files but there aren't any docs, so I could not find a way or a description of how to do this.
const express = require('express');
const app = express();
const ms = require('mediaserver');
app.get('/video', function(req, res){
const filename = 'sample1.mp4'
const filename1 = 'sample2.mp4'
ms.pipe(req, res, assetsPath + filename);
console.log ('[streaming video]: ' + filename);
});
app.listen(3000, function () {
console.log('Listening on port 3000...');
});
The best way to dynamically host files that I could find is to have a generic 'streaming' route and then pass the file as a query:
const express = require('express');
const app = express();
const ms = require('fs');
app.get('/stream', function(req,res){
var fileId = req.query.id,
file = __dirname + fileId;
fs.exists(file,function(exists){
if(exists) {
console.log("[Streaming:] %s", file);
var rstream = fs.createReadStream(file);
rstream.pipe(res);
} else {
console.log("[ERROR Streaming:] %s", file);
res.send("Playback 404");
res.end();
}
});
});
app.listen(3000, function () {
console.log('Listening on port 3000...');
});
You can then look through a directory and create a html string to send to the page, creating a button that streams the files on click:
var serverAddress = "http://localhost:3000"
var file = "sample.mp4"
stream = "<a href='" +serverAddress+ "/stream?id=" + file + "' target='_blank'><button class='btn btn-success'>Stream</button></a>";
res.send (stream)
I'm using Mongoose to create a schema and attempting to add data to mongoDB via Postman and it is adding empty data to the db. I'm assuming my issue is the way the data is parsed from browser to server here is my app.js setup.
what is added to DB
{ "_id" : ObjectId("57846282c7b5f51d4c1742a9"), "__v" : 0 }
Here is the app.js file
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var multer = require('multer');
var routes = require('./routes/index');
var mongoose = require('mongoose');
var db = mongoose.connection;
mongoose.connect('mongodb://localhost/growlingRabbit');
var Page = require('./models/growling_rabbit_page_text.js');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('userPhoto');
app.post('/api/photo',function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
app.post('/api/text',function(req,res){
var text = new Page();
text.name = req.body.name;
text.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Text Added!' });
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
module.exports = app;
Here is the model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var pageSchema = new Schema({
homePage: String,
communityPage: String,
eventPage: String,
contactPage: String,
galleryPage: String });
module.exports = mongoose.model('Page', pageSchema);;
Help, I'm sure it is something painfully obvious, unfortunately I cannot find it.
Well you create a Page with
var text = new Page();
text.name = req.body.name;
but your schema has no name property.
Change your schema like so:
var pageSchema = new Schema({
name: String,
homePage: String,
communityPage: String,
eventPage: String,
contactPage: String,
galleryPage: String });
Another problem could be using the wrong option for posting the data via Postman.
Ensure that x-www-form-urlencoded is used when testing your node API
I am trying to upload images to node.js express
bodyParser need a middleware to handle the image file , or it will reply
token undefine
I use Multer as middle ware , as this said, the req.file should hole a array of information, than I can use req.file.image.path to get the file path and other information, than I can save it as a file.
Here is the problem, I upload an image from Postman, I only write console.log(req.file) it shows undefined.
If I try to write req.file.image.path to get the file path, the error is image undefined, it seems like I didn't use multer well, so the req.file didn't hold the data information, Should I create some temp folder to multer or...?
app.js
var express = require('express')
,bodyParser = require('body-parser')
,app = express()
,multer = require('multer')
,binary = require('binary')
,fs = require('fs')
,util= require('util')
,http = require('http')
,multer = require('multer')
,upload = multer({ dest: '/Node/file-upload/uploads/' });
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies.
app.use(bodyParser.json({limit: '5mb'}));
songs = require('./routes/route');
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
app.post('/upload',songs.upload);
route.js
var mongoose = require('mongoose');
var uri = "mongodb://1111:1111#ds061365.mongolab.com:61365/aweitest";
mongoose.connect(uri);
// we're connected!
var db = mongoose.connection.db;
var BSON = require('bson').BSONPure;
var binary = require('binary');
var body = require('body-parser');
var fs = require('fs');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, '/Node/file-upload/uploads/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('image');
db.on('error', console.error.bind(console, 'connection errrrrrrrror:'));
db.once('open', function() {
console.log("mongodb is connected!!");
});
exports.upload = function(req, res) {
upload(req,res,function(err) {
console.log(req.file);
fs.readFile(req.file.image.path, function (err, data){
var dirname = "/Node/file-upload/uploads/";
var newPath = dirname + req.body.filename;
fs.writeFile(newPath, data, function (err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
});
};
error
TypeError: Cannot read property 'image' of undefined
at c:\Users\awei\WebstormProjects\untitled\routes\girlshanlder.js:107:28
You need to set the filename before send the image in the Postman as shown here
Cheers.
Full code for uploading images in your MySQL database and in folder too.
Just define the module and install multer and path and save it.
var multer = require('multer');
var path = require('path');
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './uploadimages')
},
filename: function(req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
app.post('/imginsert',multer({
storage: storage,
fileFilter: function(req, file, callback) {
var ext = path.extname(file.originalname)
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg')
{
return callback(res.end('Only images are allowed'), null)
}
callback(null, true)
}
}).single('img'), function(req, res) {
/*img is the name that you define in the html input type="file" name="img" */
var data = {
table_column_name(your database table column field name) :req.file
};
var query = connection.query("Insert into tablename set ?" ,data,function(err, rows)
{
if (err)
throw err;
res.redirect('/blog');
});
console.log(query.sql);
console.log(req.file);
});