capture String and store it in mongoDB - node.js

I'm trying to capture a text-generated string (client / session based) for when a user is uploading an image.
Output when doing db.collection.find(); from console when uploading:
"_id" : ObjectId("590c67f472667e031fe80a9d"),
"path" : "uploads/bicycle.jpg",
"originalname" : "bicycle.jpg",
"__v" : 0
Here I want to have "imagelocation" : "N/A" also.
The string is based on a users location when uploading the image.
I want to connect that specific strings value to the image-objects ID as displayed above.
App.js:
/image UPLOAD TO MONGODB
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var path = require('path');
app.use(bodyParser.json());
//To get the access for the functions defined in imagefile.js class
var routes = require('./imagefile');
// connect to mongo,
mongoose.connect('mongodb://localhost:27017/gps');
app.use('/', routes);
// To get all the images/files stored in MongoDB
app.get('/images', function(req, res) {
routes.getImages(function(err, genres) {
if (err) {
throw err;
}
res.json(genres);
});
});
app.get('/images/:id', function(req, res) {
routes.getImageById(req.params.id, function(err, genres) {
if (err) {
throw err;
}
res.send(genres.path)
});
});
path and originalname are declared as follows in my imagefile.js:
var imageSchema = mongoose.Schema({
path: {
type: String,
required: true,
trim: true
},
originalname: {
type: String,
required: true
},
imagelocation:{ // format for storing
type: String,
required: true
}
});
module.exports = mongoose.model('Image', stringClass);
var Image = module.exports = mongoose.model('files', stringClass);
router.getImages = function(callback, limit) {
Image.find(callback).limit(limit);
}
router.getImageById = function(id, callback) {
Image.findById(id, callback);
}
router.addImage = function(image, callback) {
Image.create(image, callback);
}
//multer
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/')
},
filename: function(req, file, cb) {
cb(null, file.originalname);
},
imagelocation: function(req,file,cb){
cb(null, $('#coordinates').innerHTML);
}
});
var upload = multer({
storage: storage
});
router.get('/', function(req, res, next) {
res.render('layouts/main.handlebars');
});
router.post('/', upload.any(), function(req, res, next) {
res.send(req.files);
var path = req.files[0].path;
var imageName = req.files[0].originalname;
var imagepath = {};
imagepath['path'] = path;
imagepath['originalname'] = imageName;
router.addImage(imagepath, function(err) {
});
});
module.exports = router;
HTML:
<p id="coordinates">String is generated here</p>
TL;DR - how would i capture a string and send that along with the image when uploading it to my MongoDB?

To send a string a long with your image file, you just send it along with your form on submission. For instance in a hidden input field.
Then, on submission, you can access it as part of the req.body object
Here's an example (from an API, but you get the idea):
app.post('/api/file', function(req, res){
var upload = multer({
storage: storage
}).single('imageFile')
upload(req, res, function(err){
if(err){
// handle any errors here ...
}
console.log(req.body)// <-- here you can access your text string as 'req.body.yourStringIdentifier'
res.json({success: true, msg: 'File uploaded'});
})
})
If you have any questions feel free to ask :)
Edit: Full example
server.js:
const express = require('express');
const multer = require('multer');
const path = require('path');
const ejs = require('ejs');
var app = express();
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
})
var storage = multer.diskStorage({
destination: function(req, file, callback){
callback(null, './uploads');
},
filename: function(req, file, callback){
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
})
app.post('/', function(req, res){
var upload = multer({
storage: storage
}).single('imageFile')
upload(req, res, function(err){
console.log(req.body.textInput);
res.end('File is uploaded');
})
})
var port = process.env.PORT || 7850
app.listen(port, function(){
console.log('Listening on port ' + port);
})
index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>INDEX</title>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data" method="post">
<input type="file" name="imageFile">
<input type="text" name="textInput">
<input type="submit" value="Upload file" name="submit">
</form>
</body>
</html>
This code works when I run it from the terminal with nodemon server.js. When the form is submitted, the contents of the text field is printed to the console.

Joel,
As per the Multer documentation, the Disk Storage
var storage = multer.diskStorage({.....})
engine gives you full control on storing files to disk and it has only two options available, destination and filename. They are both functions that determine where the file should be stored.
Destination is used to determine within which folder the uploaded files should be stored
Filename is used to determine what the file should be named inside the folder.
Hence your way of defining the multer.diskStorage is wrong.
If you are trying to upload it into MongoDB refer the following link:
https://ciphertrick.com/2017/02/28/file-upload-with-nodejs-and-gridfs-mongodb/
If you want to store the file in disk storage and then upload some information about the file that is stored using your schema
var imageSchema = mongoose.Schema({
path: {
type: String,
required: true,
trim: true
},
originalname: {
type: String,
required: true
},
imagelocation:{ // format for storing
type: String,
required: true
}
});
Then make changes in
var imagepath = {};
imagepath['path'] = path;
imagepath['originalname'] = imageName;
/* provide logic here as mentioned by David Stenstrøm to read it
from request.body and move it to the image schema object */
router.addImage(imagepath, function(err) {
});
Hope I clarified your query :) :)

Related

Unable to import csv to mongo through post method in node

i wanted to create a fronted with a input type file for uploading data to my mongodb collection. I used the below code buts its giving me the following error
Error: ENOENT: no such file or directory, open 'C:\Users\User\cogazzimport\public\uploads\fcnewimport.csv'
My Codes
app.js
...
var storage = multer.diskStorage({
destination:(req,file,cb)=>{
cb(null,'./public/uploads');
},
filename:(req,file,cb)=>{
cb(null,file.originalname);
}
});
var uploads = multer({storage:storage});
//init app
var app = express();
//set the template engine
app.set('view engine','ejs');
//fetch data from the request
app.use(bodyParser.urlencoded({extended:false}));
//static folder
app.use(express.static(path.resolve(__dirname,'public')));
var temp ;
let url = "mongodb://localhost:27017/";
app.post('/',uploads.single('csv'),(req,res)=>{
csvtojson()
.fromFile(req.file.path)
.then(csvData => {
console.log(csvData);
mongodb.connect(
url,
{ useNewUrlParser: true, useUnifiedTopology: true },
(err, client) => {
if (err) throw err;
client
.db("coggaz")
.collection("idata")
.insertMany(csvData, (err, res) => {
if (err) throw err;
console.log(`Inserted: ${res.insertedCount} rows`);
client.close();
});
}
);
});
});
//assign port
var port = process.env.PORT || 3010;
app.listen(port,()=>console.log('server run at port '+port));
index.ejs
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="csv"><br><br>
<div class="text-center"><button type="submit" class="btn btn-lg btn-primary">submit</button></div>
</form>
I tried various solutions but still getting the same error. Any solution with a correction code would be appreciated
use this code
var storage = multer.diskStorage({
destination:(req,file,cb)=>{
cb(null,'./public/uploads');
},
filename:(req,file,cb)=>{
cb(null,file.originalname);
}
});
var uploads = multer({storage:storage});
router.post('/import_data', uploads.single('file'), async (req, res) => {
try {
// importing csv file to database
const jsonArray = await csv().fromFile(req.file.path);
const roles = await Role.insertMany(jsonArray)
await roles.save()
res.send({msg:"csv data saved successfully"})
} catch (e) {
res.send(e)
}
use this and change Schema according to your databse name

Upload file to Local directory as well as MongoDB

I am having an issue in uploading the file to pc as well as DB at same time.
I am using two different Modules in my code
Multer: For uploading file from front-end to PC
CSV-to-JSON: For converting CSV File to json in order to store that file in Database.
But, using two separate functions isn't my intention at all.
So, when I tried combining both modules along with the base code, File uploading with Multer works but I want to upload that file to MongoDB which need to be solved by csv-to-json is a problem for me nothing seem's to be working.
here's is my code :
var express = require('express');
var multer = require('multer');
const csv = require('csvtojson');
// Import Mongodb
const mongoClient = require('mongodb').MongoClient,
assert = require('assert');
var filename = null;
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/')
},
filename: function(req, file, cb) {
filename = Date.now() + '-' + file.originalname;
cb(null, filename)
console.log(filename);
}
})
var upload = multer({
storage: storage
})
var app = express();
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.post('/', upload.single('file-to-upload'), function(req, res, next) {
// Mongodb Connection URL
const url = 'mongodb://localhost:27017/csvfilereader';
// Use connect method to connect to the Server
mongoClient.connect(url, (err, db) => {
assert.equal(null, err);
if (db) {
console.log("Connected correctly to server");
insertDocuments(db, function() {
db.close();
});
} else {
console.log('\n', 'Problem with connection', err)
}
});
const insertDocuments = (db, callback) => {
// Get the documents collection
let collection = db.collection('uploaded');
// CSV File Path
const csvFilePath = 'uploads/' + filename;
console.log(csvFilePath);
/**
* Read csv file and save every row of
* data on mongodb database
*/
csv()
.fromFile(csvFilePath)
.on('json', (jsonObj) => {
collection.insert(jsonObj, (err, result) => {
if (err) {
console.log(err);
} else {
console.log('suceess');
res.redirect('/');
filename = null;
}
});
})
.on('done', (error) => {
console.log('end')
})
}
});
app.listen(3200);
<!--
HTML Code that runs on Root
-->
<html lang="en">
<head>
<title>Simple Multer Upload Example</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<form action="/" enctype="multipart/form-data" method="post">
<input type="file" name="file-to-upload">
<input type="submit" value="Upload">
</form>
</body>
</html>
You need to access the file name through the passed request from multer. Your filename variable doesn't point to any object.
req.file.filename will give access to your file that has been uploaded by multer.
UPDATED CODE:
var express = require("express");
var multer = require("multer");
const csv = require("csvtojson");
// Import Mongodb
const MongoClient = require("mongodb").MongoClient,
assert = require("assert");
var filename = null;
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, "uploads/");
},
filename: function(req, file, cb) {
filename = Date.now() + "-" + file.originalname;
cb(null, filename);
},
});
var upload = multer({
storage: storage,
});
var app = express();
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post("/", upload.single("file-to-upload"), function(req, res, next) {
// Connection URL
const url = "mongodb://localhost:27017";
console.log("Multer", req.file.filename);
// Database Name
const dbName = "csvreader";
// Create a new MongoClient
const client = new MongoClient(url, { useNewUrlParser: true });
// Use connect method to connect to the Server
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected successfully to database");
const db = client.db(dbName);
insertDocuments(db, function() {
console.log("Closing connection");
client.close();
});
});
const insertDocuments = (db, callback) => {
// Get the documents collection
const collection = db.collection("uploaded");
// CSV File Path
const csvFilePath = "uploads/" + filename;
console.log("Reading file from ", csvFilePath);
/**
* Read csv file and save every row of
* data on mongodb database
*/
csv()
.fromFile(csvFilePath)
.then(jsonObj => {
console.log(jsonObj);
collection.insert(jsonObj, (err, result) => {
if (err) {
console.log(err);
} else {
console.log("suceess");
res.redirect("/");
filename = null;
callback();
}
});
})
.catch(err => {
//error reading file
console.log(err);
});
};
});
app.listen(3200, () => {
console.log("Server working at port 3200");
});

How to upload/save and show pictures with Mongoose,Express, Angular 4 and NodeJS

I am using Mongoose, Express, Angular 4 and NodeJS to create an app, and I am quite new to the language.
In one of my components I have a CRUD that I would like to upload a picture.
After saving it to Mongoose/MongoDB, I want to show the picture on the screen.
Should I use a plugin? If so, which one? Can you post an example?
If you want to upload file to server, you can use multer module for nodejs which is available with npm.
This site will be very helpful for you.
- https://www.terlici.com/2015/05/16/uploading-files-locally.html
And, if you want use multer with mongoose, this example will be also helpful.
Image.js
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const Image = new Schema({
filename: {
type: String,
required: true
},
originalname: {
type: String,
required: true
}
}, {timestamps: true})
module.exports = mongoose.model('Image', Image)
server.js
// ...
const app = express()
const Image = require('./Image.js')
const multer = require('multer')
const path = require('path')
const UPLOAD_PATH = path.resolve(__dirname, 'path/to/uploadedFiles')
const upload = multer({
dest: UPLOAD_PATH,
limits: {fileSize: 1000000, files: 5}
})
// upload image
app.post('/api/image', upload.array('image', 5), (req, res, next) => {
const images = req.files.map((file) => {
return {
filename: file.filename,
originalname: file.originalname
}
})
Image.insertMany(images, (err, result) => {
if (err) return res.sendStatus(404)
res.json(result)
})
})
// get image with id
app.get('/:id', (req, res, next) => {
Image.findOne({_id: req.params.id}, (err, image) => {
if (err) return res.sendStatus(404)
fs.createReadStream(path.resolve(UPLOAD_PATH, image.filename)).pipe(res)
})
})
// ...
client.js
// ...
const axios = require('axios')
function uploadImage () {
const files = document.getElementById('INPUT_TAG').files
const formData = new FormData()
formData.append('image', files[0])
axios.post('YOUR_URL/api/image', formData)
}
// ...
upload.html
<body>
<input type="file" id="INPUT_TAG"/>
<button>call uploadImage() with angular/vue/react/etc</button>
</body>
image.html
<body>
<img src="YOUR_URL/api/image/IMAGE_ID">
</body>

Error uploading files using Multer in NodeJs

I am trying to write an Express-based API for uploading files. The filename and directory path should be set dynamically.
My code:
var crypto = require('crypto')
var express = require('express');
var fs = require('fs');
var mime = require('mime');
var mkdirp = require('mkdirp');
var multer = require('multer');
var app = express();
var path = './uploads';
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, path);
console.log('Im in storage destination'+path);
},
filename: function (req, file, callback) {
console.log('Im in storage filename'+path);
//callback(null, file.fieldname + '-' + Date.now());
crypto.pseudoRandomBytes(16, function (err, raw) {
callback(null, Date.now() + '.' + mime.extension(file.mimetype));
});
}
});
var upload = multer({ storage : storage}).single('userPhoto');
app.post('/photo',function(req,res){
path += '/pics/shanmu/';
console.log('Im in post , outside upload'+path);
upload(req,res,function(err) {
console.log('Im in post , inside upload'+path);
if(err) {
return res.end('Error uploading file.');
}
res.end('File is uploaded'+path);
console.log('File is uploaded'+path);
});
});
app.listen(3000,function(){
console.log('Working on port 3000');
});
My folder structure:
When I run the code, the file should be uploaded in the uploads/ folder. (This folder has two nested folders inside it - uploads/pics/shanmu).
When I triggered it from postman, it only works once. When I try the second time, I cannot upload files.
Please advise.
Working on sometime I got a solution using multer module.Using this module you can upload both files and images.And it successfully uploaded to the destination folder.
Here is my server code app.js
var express =r equire('express');
var multer = require('multer');
var path = require('path')
var app = express();
var ejs = require('ejs')
app.set('view engine', 'ejs')
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './public/uploads')//here you can place your destination path
},
filename: function(req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
app.get('/api/file',function(req,res){
res.render('index');
});
app.post('/api/file', function(req, res) {
var upload = multer({
storage: storage}).single('userFile');
upload(req, res, function(err) {
console.log("File uploaded");
res.end('File is uploaded')
})
})
app.listen(3000,function(){
console.log("working on port 3000");
});
Create a views folder and place this index.ejs file in it
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data" method="post">
<input type="file" name="userFile" />
<input type="submit" value="Upload File" name="submit">
</form>
</body>
</html>
After this run the server as node app.js.Open the browser and type http://localhost:3000/api/file after runnig this url choose a file which you want to upload to destination folder.And have a successfull response in both terminal and browser.Hope this helps for you.
I got your code working. See:
https://gist.github.com/lmiller1990/3f1756efc07e09eb4f44e20fdfce30a4
I think the problem was with the way you declared destination. I'm not sure why, though. I got it working by just passing the path as a string.
Best of luck!

Node.js - expressjs - multer req.files outputs empty

i'm using multer to get a file from this form
<form action="/api/pimage" method="POST" enctype="multipart/form-data">
<fieldset>
<input type="file" name="profileimage">
<input type="submit">
</fieldset>
</form>
using this serverside script
app.post('/api/pimage', function(req, res, next) {
console.log(req.body, req.files);
});
the problem is that req.body is printing out { profileimage: 'image.png' }
and req.files is printing out {}
where you see the problem?
thanks
P.S. i'm using app.use(bodyParser.urlencoded({ extended: false })); to get req.body and app.use(multer({ dest: './uploads/'})); for req.files
I found that using multer alongside bodyParser can cause req.file to be undefined. Make sure to check that also if you're having issues.
I put MY (there are many I imagine and surely better) solution to help many people like me because I have searched during 1 entire day ;-(
var express = require('express');
var fileUpload = require('express-fileupload');
var fs = require("fs");
var app = express();
console.log('étape 0');
app.use(express.static('mesStatic'));
app.use(fileUpload());
console.log('étape 1');
app.get('/indexFileUpload.htm', function (req, res) {
res.sendFile( __dirname + "/" + "indexFileUpload.htm" );
})
console.log('étape 2');
app.post('/file_upload', function (req, res) {
console.log('étape 3');
console.log('req.files:' , req.files);
if (!req.files) {
res.send('No files to upload.');
return;
}
console.log('req.files.file.data:' , req.files.file.data);
var bufDataFile = new Buffer(req.files.file.data, "utf-8");
console.log('étape 3.1');
console.log('__dirname : ' + __dirname);
fs.writeFile(__dirname + '/file_upload/output.txt', bufDataFile, function(err) {
if (err) {
return console.error(err);
}
else {
console.log("Data written successfully !");
}
console.log('étape 4');
res.end('Fin OK !!!');
})
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port);
})
You have to provide your upload function defined for multer before asking for req.file in function(req, res), you can follow the code given below
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./images/");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: Storage }).single('imagePath');
router.post('/file_upload', upload, function(req, res, next){
console.log(req.file);
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./public/images/");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: Storage }).single('imagePath');
router.post('/add-product', upload, function(req, res, next){
var newProduct = new Product();
}

Resources