EJS can't find image in static public folder - html

I'm trying render a html template as a PDF using EJS, however the images are not appearing.
My project structure:
- public
- images
image.jpg
- routes
documentsRoute.js
- services
documentsService.js
- views
document-template.ejs
server.js
I am setting the public folder as a static folder in my server.js like so:
...
const app = express()
app.use(express.static('public'))
...
In my template file I'm using this as my src for the image
<img src="images/image.jpg" alt="my_image">
I'm rendering the file from my document service like so:
ejs.renderFile('views/document-template.ejs', inputs, (err, data) => {
if (err){
throw err;
}
let options = {
"format": "A4",
"header": {
"height": "20mm"
},
"footer": {
"height": "20mm"
}
};
pdf.create(data, options).toFile('test.pdf', (err, res) => {
if(err){
throw err;
}
});
})
The rest of the template is rendered correctly, just not the image, instead it shows the alt text. Does anyone know how I could fix this?

You need to set the view directory correctly in your server file.
So instead of app.use(express.static('public'))
try
app.use(express.static( path.join(__dirname, './public')))

it's rather pdf having trouble with the path. try using absolute path
add full path in the base property of pdf options:
let options = {
"format": "A4",
//...
base: `${req.protocol}://${req.headers.host}`
};

Related

Inject .html file from packed chrome extension directory into new window tab

I am building a Chrome extension (v3) and I am trying to load an index.html from the extension's directory, and replace the old html with my html in a newly created window. But instead of html, it gets rendered as text. This is what I got so far:
I stored the html file in my background.js :
let template = chrome.runtime.getURL("assets/index.html");
chrome.runtime.onInstalled.addListener( () => {
chrome.storage.sync.set({ "data": {"template" : template } });
});
In my popup.js, I first created a new window. Then I tried to inject a content script that overwrites the current html with my index.html file, as seen below:
button.addEventListener("click", async () => {
//get url of current tab
let tab = await chrome.tabs.query({ active: true, currentWindow: true });
//create new window
let newWindow = await chrome.windows.create({
url : tab[0].url,
type : "popup",
width: dims.cssWidth,
height: dims.cssHeight,
state: "normal"
})
const tabId = newWindow.tabs[0].id;
if (!newWindow.tabs[0].url) await onTabUrlUpdated(tabId);
const results = await chrome.scripting.executeScript({
target: {tabId},
function: setBackground,
});
});
setBackground() function to remove existing html and replace it, but keep url tab[0].url from active page to embed it as an iframe
function setBackground(){
chrome.storage.sync.get("data", ({ data }) => {
document.write(data.template);
//add tab[0].url as iframe
});
}
How can I replace the new window with my own html rather than render text?
One way of reading the contents of a local .html file with fetch would be the following:
function setBackground(){
try {
//fetch local asset
const res = await fetch(chrome.runtime.getURL("/assets/index.html"));
const myhtml = await res.text()
document.write(myhtml);
} catch(err){
console.log("fetch error", err);
}
}

Return image from Node REST API and use in img.src on client-side

I am storing images in MongoDB as base64 string. I created Express route to get image by id:
router.get('/:userId/images/:imgId', (req, res) => {
Image.findOne(
{ _id: req.params.imgId },
(err, img) => {
if (err) {
res.status(500).send('someErr');
} else {
var resultImg = Buffer.from(img.data, 'base64');
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': resultImg.length
});
res.end(resultImg);
}
}
);
});
Client-side:
<img src={`api/users/${userId}/images/${imgId}`} />
What I am sure about:
path is correct, server receives request and returns 200 response
data is correctly fetched from MongoDB
base64 string is correct (when I copy paste to verifier like https://codebeautify.org/base64-to-image-converter, it is working)
Why images are not loaded?
make sure the output has this string at the beginning
<img src='data:image/png;base64,your base 64 goes here'/>
you can test by copying the output and put it in a static html and see does it work.
so may be something like this would help
<img src=`data:image/png;base64,{`api/users/${userId}/images/${imgId}`}`/>
Have you try hit your backend using AJAX or Fetch API ?
After that, you can load response from that API into your image element

How to make a pdf Generator with ionic?

I want to make a pdf of the current page so the user can print it out but every page is dynamic so I will need a sort of a text to pdf generator to make it work.
It is an ionic2 app and is for like a recipe page so you can click on a button and it just makes a pdf out of the text.
Do you guys know how I can achieve that?
Your best bet is probably this plugin:
https://github.com/cesarvr/pdf-generator
give your dynamic page section an id like 'pdf-area' and then select it in your .ts file like this:
let content = document.getElementById('pdf-area').innerHTML
you can then turn that into a file or print it like this
cordova.plugins.pdf.htmlToPDF({
data: content,
type: "base64"
},
(success) => {
// you might have to turn the base64 into a binary blob to save it
// to a file at this point
},
(error) => console.log('error:', error);
);
}
put your html in assets folder and give the html path like this.
In my case this path is working:
var file = 'file:///android_asset/www/assets/lolc.html';
generatePdf(){
const before = Date.now();
document.addEventListener('deviceready', () => {
console.log('DEVICE READY FIRED AFTER', (Date.now() - before), 'ms');
var file = 'file:///android_asset/www/assets/lolc.html';
cordova.plugins.pdf.fromURL(file,{
documentSize: "A4",
landscape: "portrait",
type: "share"
}),
(sucess) => console.log('sucess: ', sucess),
(error) => console.log('error:', error);
});
}

Can't get xlsx to JSON converter to work properly in Node/Express

I am using the package below to try to convert uploaded excel files (.xlsx) to JSON files on my Express web application:
https://www.npmjs.com/package/xlsx-to-json
So here is my form for the user to upload:
form(id = "form1", action="/upload", method="post", enctype="multipart/form-data")
input(type="file", id="control", name="XLupload")
br
input(type="submit" value="Upload" name="Submit")
and here is my routing for the upload back in my main express (app.js) file:
var multer = require('multer');
var upload = multer({dest: './uploads'});
var excel_upload = upload.single('XLupload');
app.post('/upload', excel_upload, function(req, res) {
var fileObject = req.file;
var filePath = fileObject.path;
/*** This is what the file Object looks like when uploaded:
{ fieldname: 'XLupload',
originalname: 'testing.xlsx',
encoding: '7bit',
mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
destination: './uploads',
filename: 'c1d55ea7d1f6fccc7e3d3d2764db8881',
path: 'uploads\\c1d55ea7d1f6fccc7e3d3d2764db8881',
size: 8013 }
***/
xlsxj({
input: String(filePath),
output: "output.json"
}, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
});
anyways, to put it shortly, the uploads seem to work fine, that is, they are uploaded to the /uploads folder in the directory. However, the JSON file that I get back from the xlsxj converter is empty and I'm not sure why. I made a small test xlsx file with some words in random cells and it still game me back an empty
[]
in output.json. Anybody can let me know what I am doing wrong?
You can try to use this library XLSX (https://github.com/SheetJS/js-xlsx) and add this code after get workssheet
var roa = XLSX.utils.sheet_to_row_object_array(worksheet);

node.js server, displaying HTML file which has jqGrid plugin included.

I have a simple HTML file which includes jqGrid plugin. I am using jqGrid plugin to have a tree grid in my HTML page.
Now, I am trying to host this HTML file in node.js server. My server.js looks like this
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request starting...');
var filePath = '.' + request.url;
console.log('filePath : '+filePath);
if (filePath == './')
filePath = './tree.html';
var extname = path.extname(filePath);
console.log('extname : '+extname);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
path.exists(filePath, function(exists) {
if (exists) {
fs.readFile(filePath, function(error, content) {
if (error) {
response.writeHead(500);
response.end();
} else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
} else {
response.writeHead(404);
response.end();
}
});
}).listen(8125);
So far, I am able to display my HTML content in browser [http://localhost:8125/]
Part of my HTML(tree.html) file looks like this
jQuery("#treegrid").jqGrid({
url: 'tree.json',
datatype: 'json',
//mtype: 'GET',
colNames: [/* "ID", */"Col 1", "Col 2",.. ],
colModel: [/* {
name: 'id',
index: 'id',
width: 1,
hidden: true,
key: true
}, */{ ...
If you can notice, I have specified 'tree.json' as URL attribute to load the tree grid. That is just reading a static file to load the tree grid with sample data.
Problem : Now, when I try to access my HTML file using [http://localhost:8125/]
I get an 404 Not Found error for [http://localhost:8125/tree.json]
Quick Solution : I can specify the relative path of the file 'tree.json' and it works.
Both my HTML file tree.html and tree.json are in the same directory (/tree) and I start my node.js server from command prompt (terminal) like this
tree> node server.js
I would like to know where I can place my tree.json in order to make my HTML work as intended.
Please feel free to ask any clarification.
Thanks in advance
You use the line
var filePath = '.' + request.url;
in your code which seems a little strange. Probably in case of request of 'tree.json' you will have .tree.json as the value of filePath instead of ./tree.json which you probably want to have. I think you should fix the code here.
Moreover it would be good to set 'application/json' as the value of contentType variable in case of .json extension in the same way like you set 'text/javascript' and 'text/css' for '.js' and '.css' files.