How to convert blob object in EJS Template - node.js

I am working on patient photo upload using express, mongodb, multer, ejs, and croppiejs. When user uploads a photo they have an option to crop it. I am saving the cropped photo in a collection as BLOB object in a field called croppedPhoto.
Now, i want to display that cropped photo on front-end. I am passing the patients object (which contains all the data fields of a record including cropped photo).
I am thinking of converting that blob object to base64 and display it. But the issue is I am not sure how to use croppedPhoto field value in ejs template to convert it.
server.js [Finding all patients and passing in to ejs template - includes croppedPhoto field as well]
app.get('/', async (req, res) => {
const patients = await Patient.find();
res.render('index', { patients: patients });
});
index.ejs [want to display the photo in img tag]
<div class="flex flex-wrap mt-10">
<% patients.forEach(patient => { %>
<div
class="flex flex-col items-center justify-center h-auto lg:h-auto lg:w-32 flex-none bg-cover rounded-t lg:rounded-t-none lg:rounded-l text-center overflow-hidden">
<img src="<%= patient.croppedPhoto %>" class="my-3 w-20 h-20 rounded-full" alt="Patient Photo">
</div>
<% }) %>
</div>
Thanks!!

Usually and when it comes to uploading files to the server, you have to avoid saving the file itself in the database, instead, you can move the file from the client's desktop to the directory you want (your application images folder where you store the images) using Express file upload , and you save the path of that file in the database, normally it would be something like this : /images/test.png .
Here is an example :
router.route('/add').post(function (req, res) {
if (req.files && req.body.name) {
var file = req.files.file
// to move the file to the direct i want !
file.mv("client/public/img/client/categories/" + file.name, err => {
if (err) {
console.error(err);
return res.status(500).send(err);
}
});
var newCategorie = new Categorie({
name: req.body.name,
imgUrl: "/img/client/categories/" + file.name // TO SAVE THE PATH
});
}
newCategorie
.save()
.then(categories => res.json(categories))
.catch(err => res.status(400).json('Error: ' + err));
} else {
res.status(400).json({ msg: "Please enter all fields" });
}
});
Then in your EJS template, it would be very easy to access the src of the image : <img src="OBJECT.ImgURL" />

Related

React reloads the page after replacing images

I am uploading images to a server. If it is present and replaced, then React refreshes the page with a loss of state. How can I stop this behavior?
Node:
let form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
let {size, path, name, type} = files.image,
newpath = pathLib.join(__dirname, '../client/public/uploads') + name;
fs.rename(path, newpath, function (err) {
if(err) throw err;
});
});
React:
<form id="uploadForm">
<input id="uploadInput" name="image" type="file" />
</form>
<span onClick={() => {
let form = document.querySelector("#uploadForm"),
formData = new FormData(form);
if(form.querySelector("#uploadInput").files.length)
uploadFiles(formData, (res) => {
console.log(res.data.errors);
});
}}>Save</span>
An important addition! Page refreshed even without interaction with React components. Replacing an image through the Windows file manager calls the re-render.
Just call event.preventDefault() when submit form. See the example here:
<form id="formSubmit"}>
<input id="uploadInput" name="image" type="file" />
<button type="submit"></button>
</form>
document.getElementById('formSubmit').addEventListener('submit',function(event){
event.preventDefault()
// write here your others code
})

How do I have a variable available to display on my success page, after adding items to a database via a /POST route?

I would like to display the doc.id variable of a successful /POST of data to a route, on the success page that the user will be redirected to afterward. I'm trying to work out how to carry the variable teamId through to the Handlebar template page success.hbs
I've tried making it a variable, and setting up a Handlebar helper to display it, but nothing is working.
/POST route redirecting to success.hbs:
app.post('/create', (req, res) => {
var players = [];
var playerObj = {};
for (let i = 1; i < 21; i++) {
var playerObj = { playerName: req.body[`player${i}Name`], playerNumber: req.body[`player${i}Number`], playerPosition: req.body[`player${i}Position`] };
if (req.body["player" + i + "Name"] === '') {
console.log("Empty player name detected, disregarding");
} else {
players.push(playerObj);
}
}
var newTeam = new Team({
// WEB SETUP BELOW
"team.teamRoster.teamCoach": req.body.coachName,
"team.shortTeamName": req.body.teamShortName,
"team.teamName": req.body.teamName,
"team.teamRoster.players": players
});
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs');
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});
});
/views/success.hbs
<div class="container-fluid" id="body">
<div class="container" id="page-header">
<h1><span id="headline">Team Added Succesfully</span></h1>
<hr>
<h3><span id="subheadline">Input the following address as a JSON Data Source within vMix.</span></h3>
<span id="content">
<div class="row">
<div class="container col-md-12">
{{{teamId}}}
</div>
</div>
</span>
</div>
<hr>
</div>
I'd like a Handlebar helper to get the doc.id value of the /POST request, and store it as teamId to display on the success page. It's finding nothing at the moment.
Any help is appreciated.
Node.js can pass variables to the handlebars-view like this:
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs', {
teamId
});
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});

Save file to mongodb using angular and Nodejs

I am trying to upload an image to mongodb using angular and nodejs. The code is below. I got the backend working but the problem is with the html input i get 'C:fakepath/file.xyz'. I was looking online and saw that there is not a way to get the relative path of the file. Can someone please tell me how i can change my front end code to get and send the file path to the backend to then save. I read that the browser doesnt allow relative path of the file but then how can I upload. Thanks!
The nodejs image save method is:
async function SaveImage(userParam) {
const entry = new imageEntries(userParam);
entry.image.data = fs.readFileSync(userParam.imagePath);
entry.image.contentType = 'image/png';
await entry.save();
}
The html code is:
<div class="upload-btn-wrapper">
<button class="btn">Upload a file</button>
<input type="file" name="myfile" id="myFile" />
</div>
What I pass as the path in the backend is:
ImageJournal.imagePath = (<HTMLInputElement>document.getElementById('myFile')).value;
but with the code above i get the following error:
ENOENT: no such file or directory, open 'C:\fakepath\chapter9problemsandanswers.doc'
Ok here it is:
HTML:
<div class="form-group">
<label for="pdf">PDF</label>
<input type="file" id="pdf" (change)="onFileChange($event)" #fileInput>
<button type="button" class="btn btn-sm btn-default" (click)="clearFile()">clear file</button>
</div>
TS:
import { Component, OnInit, ElementRef, ViewChild } from '#angular/core';
#ViewChild('fileInput') fileInput: ElementRef;
public image;
onFileChange(event) {
let reader = new FileReader();
if(event.target.files && event.target.files.length > 0) {
let file = event.target.files[0];
reader.readAsDataURL(file);
let value = <String>reader.result;
reader.onload = () => {
this.image = {
filename: file.name,
filetype: file.type,
value: value.split(',')[1]
};
};
}
}
Then send the image with http post with a service.
On the server:
// send file
app.post('/api/sendFile', function (req, res) {
File.create({
filename: req.body.filename,
filetype: req.body.filetype,
value: req.body.value
}, function (err, file) {
if (err)
res.send(err);
else {
const response = {
name: file.filename
}
res.send(response);
}
});
});
This is written with mongoDb and mongoose and I have a model named File.
This is all it need to save it.

Multer - Cannot Read Property "path" of Undefined

I'm trying to upload a single image to mongo using multer but I keep getting this error while trying to access the image path like:
TypeError: Cannot read property 'path' of undefined
at router.post (D:\Workspace\AdminBootstrap\routes\admin_index.js:74:29)
Here's my code to upload the image:
router.post('/add-category', uploads.single('category_image'), (req, res) => {
let title = req.body.title;
console.log('Category Title:\t' + title);
let slug = title.replace(/\s+/g, '-').toLowerCase();
let catImage = req.file.path; // error occurs here
console.log(catImage);
let category = new Category({
title: title,
slug: slug,
image: catImage
});
category.save()
.then(result => {
if (result) {
console.log('Saved Category:\t' + result);
res.redirect('/admin/home');
}
})
.catch(errors => {
console.error('Error Saving Category:\t' + errors);
});
});
Here's my template:
<label>Upload Image</label>
<input name="category_image" class="form-control" type="file" accept="image/*" id="selImg" onchange="showImage.call(this)">
<img src="#" id="imgPreview" style="display: none; height: 100px; width: 100px">
Can anyone explain to me why the path is throwing an error?
The path is throwing an error because "file" is not defined inside "req" object.
It is probably defined in "req.body" object. Use
console.log(req.body)
to confirm.
Since title is defined on "req.body", "file.path" also should be defined on the same object.
While setting up your HTML, your form should have an attribute of
enctype="multipart/form-data"
This will save your file in the path variable

post input type file to server node.js from angular service call

I have simple multipart formdata
<form action="/upload" enctype="multipart/form-data" method="post">
<span class="btn btn-file">
<input type="file" name="file" ng-model="file"/>
<span class="btn btn-primary" ng-click="upload()">Upload</span>
</span>
</form>
What I want to do it, post all the information related to file to the server written in node.js
server.js This is file upload handler written in node. Formidable expects all parameters of a file.
upload: function uploadfn (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// `file` is the name of the <input> field of type `file`
var old_path = files.file.path,
file_size = files.file.size,
file_ext = files.file.name.split('.').pop(),
index = old_path.lastIndexOf('/') + 1,
file_name = old_path.substr(index),
new_path = path.join(process.env.PWD, '/uploads/', file_name + '.' + file_ext);
fs.readFile(old_path, function(err, data) {
fs.writeFile(new_path, data, function(err) {
fs.unlink(old_path, function(err) {
if (err) {
res.status(500);
res.json({'success': false});
} else {
res.status(200);
res.json({'success': true});
}
});
});
});
});
}
The things I'm stuck at is, I have service call ready in angular as follows:
service.factory('FileUpload', function ($resource) {
return $resource('/upload', {}, {
post: {method: 'POST'}
});
});
This call hits the backend from angular controller as follows
$scope.upload = function(){
console.log($scope.file);
FileUpload.post(function(){
});
}
I'm not sure how to post the file submit so that node can catch it. Also $scope.file is undefined.
Please help me solve this.
There's a good directive for file upload for angularjs, try to use it
https://github.com/danialfarid/angular-file-upload

Resources