Issue regarding converting of Arraybuffer of image to image and displaying it in html page - node.js

I have my js code as
app.get("/", function(req, res) {
var sql="SELECT image FROM images WHERE img_id=2";
connection.query(sql, function(err, result){
if(result.length <= 0)
message = "Profile not found!";
console.log(result);
res.render('image.ejs',{data:result});
});
});
and the image.ejs code is:
<html>
<head>
<title>Images</title>
</head>
<body>
<%= data %>
</body>
</html>
When I have runned it I just got the response like
[object Object]
but I need to my image to get displayed.will you guys help me out?

An ArrayBuffer/Buffer can't be a value for an img tag, what you can do is base64 encode the image, and display it
res.render('image.ejs',{ data: result[0].image.toString('base64') });
Now on your HTML
<html>
<head>
<title>Images</title>
</head>
<body>
<img src='data:image/png;base64,<%= data %>' />
</body>
</html>
If your images have different extensions, you can use: file-type package on the buffer and add the image type to the data passed to res.render
const imageBuffer = result[0].image;
const { mime } = await FileType.fromBuffer(imageBuffer)
res.render('image.ejs', { data: imageBuffer.toString('base64'), mime });
<img src='data:<%= mime %>;base64,<%= data %>' >

Related

Destroy Darkroom / Fabric JS Canvas

$(function() {
$('button').on('click', function() {
new Darkroom('#edit', {
plugins: {
save: {
callback: function() {
console.log('saving');
var darkroom = this.darkroom;
darkroom.canvas.clear().renderAll();
darkroom.selfDestroy();
return true;
}
}
}
});
});
});
<html>
<head>
<link href="https://rawgithub.com/MattKetmo/darkroomjs/master/build/darkroom.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.2/fabric.min.js"></script>
<script src="https://rawgit.com/MattKetmo/darkroomjs/master/build/darkroom.js"></script>
</head>
<body>
<div style="margin-top:50px">
<img id="edit" class="data-uri-example" src="data:image/gif;base64,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">
</div>
<button type="button">Edit</button>
</body </html>
Using darkroom js and fabric js. After I save the canvas data I want to remove the img/canvas from the page. The original img tag used in initialization '#edit' is no longer an element on the page. Seems it's replaces by a new img.
I've tried the .clear() also .clear().renderAll(). I get no error but the image still shows on the page.
Remove div element for control Darkroom and in code create again
$(function () {
$('button').on('click', function () {
$('#main-el').html('');
$('#main-el').append('<img id="edit" class="data-uri-example" src="...">');
new Darkroom('#edit');
});
});

html-pdf npm library gives different output on windows & ubuntu

I'm using https://www.npmjs.com/package/html-pdf library which is based on Phantom JS which internally uses webkit. I'm pasting the dummy HTML & JS code(keep these files in 1 folder) and also attaching the output screenshot.
The issue I'm facing is that on windows the PDF is generated with some extra space at top(empty space above red) which I can't get rid of.
Here is a forum(outdated) discussing similar issues, https://groups.google.com/forum/#!topic/phantomjs/YQIyxLWhmr0 .
input.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="pageHeader" style="border-style: solid;border-width: 2px;color:red;">
header <br/> header <br/> header <br/> header
</div>
<div id="pageContent" style="border-style: solid;border-width: 2px;color:green;">
<div>
body <br/> body <br/> body
</div>
</div>
JS
(You require path, fs, handlebars, html-pdf npm packages)
var path = require('path');
var fs = require('fs');
var handlebars = require('handlebars');
var pdf = require('html-pdf');
saveHtml();
function saveHtml() {
fs.readFile('input.html', 'utf-8', {
flag: 'w'
}, function(error, source) {
handlebars.registerHelper('custom_title', function(title) {
return title;
})
var template = handlebars.compile(source);
var data = {};
var html = template(data);
var options = {
'format': 'A4',
'base': "file://",
/* You can give more options like height, width, border */
};
pdf.create(html, options).toFile('./output.pdf', function(err, res) {
if (err) {
console.log('err pdf');
return;
} else {
console.log('no err pdf');
return;
}
});
});
}
Output on ubuntu
Output on windows
Extra space at top(empty space above red) in Windows is the issue.
THINGS that didn't work
1. Adding
"border": {
"top": "0px" // or mm, cm, in
}
to options in JS file
https://www.npmjs.com/package/html-pdf#options
Giving fixed "height": "10.5in" & "width": "8in" in options in JS file
Making margin-top & padding-top to 0px/-50px to pageHeader div.
Overriding margin-top & padding of body to 0px/-20px in #media print in bootstrap.css
Giving fixed height to header
Any help will be greatly appreciated. Thanks.
You can manually set the CSS property to html tag. In my case I was having problems developing the template in Windows and deploying it to Linux (Heroku).
I put zoom: 0.7 in the label html and now both views look the same.
html{zoom: 0.7;}
I was able to get more consistent results by removing the ID's so that it treated everything as content rather than separate header and content areas.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="border-style: solid;border-width: 2px;color:red;">
header
</div>
<div style="border-style: solid;border-width: 2px;color:green;">
<div>
body
</div>
</div>
</body>
</html>
If you need an ID for styling, use something other than pageHeader / pageFooter to avoid the special treatment associated with those IDs.
Have you tried using a normalize style sheet to compensate for cross platform differences?
https://necolas.github.io/normalize.css/

Node Express EJS Dynamic template render

Hi I am trying to create dynamic template system in express, where I will get dynamic content from database and then render output in single index.ejs file.
Here is my index.js
router.get('/', function(req, res, next) {
var dataFrmDB = {
pageContent: "<%= data.pageTitle %>",
pageTitle: "home"
};
res.render('index', {data:dataFrmDB} );
});
And index.ejs contains:
<%= data.pageContent %>
What I should do so that I can render "home" as output. Is this possible?
I was working on something similar when we migrated from drupal to nodejs, I used ect for rendering instead of jade, its faster and much easier to deal with, However, its much better to use design pattern if you have a big dynamic website
js controller file
model.homepage(function(data)
{
res.render("homepage.ect",data,function(err,html)
{
// Do something before you send the response such as minification, or error handling
res.send(html);
});
});
ECT file
<html xmlns="http://www.w3.org/1999/xhtml" lang="ar" xml:lang="ar">
<head>
<%- #page.title.body %>
<%- #page.headerScript.body %>
<style type="text/css">#homepage-container{min-height:300px;color:#353535;float:right;width:100%}</style>
</head>
<body>
<% include 'upper_bar.ect' %>
<%- #page.headerAd.ads %>
<%- #page.notifications.body %>
<%- #page.autocomplete.body %>
<%- #page.redirect.body %>
<%- #page.navigation.body %>
<%- #page.overlayAd.ads %>
</body>
</html>
why bother so much?
You can easily do this using templatesjs
without any template engine.
let me show you how your work can be done using templatesjs
html file
<html>
<head>
<title> <%title%> </title>
</head>
<body>
your content goes here
</body>
</html>
now use templatesjs in you node.js file
var tjs = require("templatsjs");
router.get('/', function(req, res, next) {
var data = fs.readFileSync("./index.html");
tjs.set(data); // invoke templatesjs
var output = tjs.render("title","home");
/* this will replace the <%title%> tag
in the html page with actual title*/
res.write(output);
res.end()
});
i have used fs.readFileSync to keep simplicity of code you can use the asynchronus function if you want (fs.readFile).
a good referrence can be found here
Installation :
$ npm install templatesjs

Writing to a particular div in node js

I have this simple file hello.html and looks like this.
<!DOCTYPE html>
<html>
<head>
<style>
p { background:yellow; }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div class="thediv">
</div>
</body>
</html>
I am using fs module to write to my file like this
var fs = require('fs');
var randomnumber = Math.floor((Math.random()*100393)+433334);
fs.createReadStream('test.txt').pipe(fs.createWriteStream(randomnumber+'.txt'));
fs.writeFile(randomnumber+".txt", "Lorem ipsum"+randomnumber, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
console.log(randomnumber);
I want to write
<article>
<p> lorem ipsum </p>
</article>
to the div with the id thediv.Is the fs module used for this kind of thing or is there a module more suited for this task?.
I believe the only answer to get an HTML parser, parse the file into a DOM, make the adjustments and then save the DOM back to a file. Here's a question that answers where to find an HTML parser.

is there a way to add CSS/JS later using EJS with nodejs/express

i'm using the EJS template engine with nodejs/express and i'm wondering if it's possible to add another css or js file in e.g the index.ejs (not the layout.ejs)
layout.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<link rel='stylesheet' href='/stylesheets/smoothness/jquery-ui-1.8.14.custom.css' />
</head>
<body>
<%- body %>
</body>
</html>
index.ejs
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
i don't want to add the second css file in every template but only the index.ejs - is there any way i can do that?
found a solution here: Node.js with Express: Importing client-side javascript using script tags in Jade views?
it's using jade instead of EJS but works all the same.
here are some code-snippets for express 2.4.0.
you have to add the following "helpers" to your app.js
app.helpers({
renderScriptsTags: function (all) {
if (all != undefined) {
return all.map(function(script) {
return '<script src="/javascripts/' + script + '"></script>';
}).join('\n ');
}
else {
return '';
}
}
});
app.dynamicHelpers({
scripts: function(req, res) {
return ['jquery-1.5.1.min.js'];
}
});
the layout.ejs looks sth like this:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<%- renderScriptsTags(scripts) %>
</head>
<body>
<%- body %>
</body>
</html>
if you don't add any scripts to the scripts-array, only 'jquery-1.5.1.min.js' will be included - if you want to add files to a subpage you can do this like so:
test.ejs
<% scripts.push('jquery-ui-1.8.14.custom.min.js', 'jquery.validate.min.js') %>
<h1><%= title %></h1>
<p>I'm a template with 3 js files in the header</p>
that's it.
As helpers and dynamicHelpers are gone in Express > 3, I rewrote pkyeck code so it works in Express 3.
So in app.js have this instead of the helpers / dynamicHelpers. Leave everything else as is.
app.locals({
scripts: [],
renderScriptsTags: function (all) {
app.locals.scripts = [];
if (all != undefined) {
return all.map(function(script) {
return '<script src="/javascripts/' + script + '"></script>';
}).join('\n ');
}
else {
return '';
}
},
getScripts: function(req, res) {
return scripts;
}
});
In app.js add line:
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public')); // This line.
In layout.ejs:
<!DOCTYPE html>
<html>
<head>
<title>Authentication Example</title>
<link rel="stylesheet" href="/stylesheets/style.css"/>
<script src="/javascripts/jquery.js"></script>
</head>
<body>
<%- body %>
</body>
</html>
In index.ejs or login.ejs:
<h1>Login</h1>
<form method="post" action="/login">
<p>
<label>Username:</label>
<input type="text" name="username">
</p>
<p>
<label>Password:</label>
<input type="text" name="password">
</p>
<p>
<input type="submit" value="Login">
</p>
</form>
<script src="/javascripts/test.js"></script> <!-- Second Script -->
In test.js:
$(document).ready(function() {
try{
alert("Hi!!!");
}catch(e)
{
alert("Error");
}
});
Regards.
Thanks #asprotte for providing this for express 4.x. Did you tested this?
Because it does not appears to be working for me. So I have made some changes to your code here are they:
Put this in app.js file
app.locals.scripts = [];
app.locals.addScripts=function (all) {
app.locals.scripts = [];
if (all != undefined) {
app.locals.scripts = all.map(function(script) {
console.log(script);
return "<script src='/js/" + script + "'></script>";
}).join('\n ');
}
};
app.locals.getScripts = function(req, res) {
return app.locals.scripts;
};
then in template file put (I am using ejs template here) :
<% addScripts(['cart.js']) %>
Then in the layout file we need these to append at the bottom of the page get the scripts
<%- getScripts() %>
I have tested it and its working for me. Please correct me if I am wrong.
Thanks,
Thanks for illustrating this option pkyeck!
In express 4.x app.locals is an object. Here's pkyeck's answer rewritten to work in express 4.x:
app.locals.scripts = [];
app.locals.addScripts=function (all) {
app.locals.scripts = [];
if (all != undefined) {
return all.map(function(script) {
return "<script src='/javascripts/" + script + "'></script>";
}).join('\n ');
}
else {
return '';
}
};
app.locals.getScripts = function(req, res) {
return scripts;
};

Resources