How can I preview a PDF on the front end using it's data sent from the back-end with Expressjs? - javascript

I sent a PDF stored on my back-end using Expressjs.
// FILE: app.js
const express = require('express');
const app = express();
var fs = require('fs');
app.use(express.static('./methods-public'));
app.get('/api/pdf', (req, res, next) => {
const path = './dog.pdf';
if (fs.existsSync(path)) {
res.contentType('application/pdf');
fs.createReadStream(path).pipe(res);
} else {
res.status(500);
console.log('File not found');
res.send('File not found');
}
});
app.listen(5000, () => {
console.log('Server is listening on port 5000....');
});
My front-end received the raw data using Javascript with Axios.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="result"></div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"
integrity="sha512-bZS47S7sPOxkjU/4Bt0zrhEtWx0y0CRkhEp8IckzK+ltifIIE9EMIMTuT/mEzoIMewUINruDBIR/jJnbguonqQ=="
crossorigin="anonymous"
></script>
<script>
const result = document.querySelector('.result');
const fetchPDF = async () => {
try {
const { data } = await axios.get('/api/pdf');
result.innerHTML = '<h3>' + data + '</h3>';
} catch (error) {
result.innerHTML = `<div class="alert alert-danger">Can't Fetch PDF</div>`;
}
};
fetchPDF();
</script>
</body>
</html>
My front end-knowledge is very limited. I've been struggling to understand how I can use this data to render the pdf then display it within a Canvas.

Related

Not able to resolve the Promise on client side JS form express res.json

I am not able to debug or figure out why my request is logging raw HTTP response as shown in the image on the browser console once the expressjs server returns the JSON response. Let me kick in all relevant code and we can talk then
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Scroll</title>
<script src="./infiniteScroll.js" defer></script>
</head>
<body>
<div id="testimonial-container"></div>
</body>
</html>
infiniteScroll.js
async function fetchAndAppendTestimonials(limit = 5, after = 0) {
const testimonials = await fetch('/testimonials');
console.log(testimonials);
}
fetchAndAppendTestimonials(5, 0);
I starting adding server.js incrementally so that I can bypass CORS to call the external API - 'https://api.frontendexpert.io/api/fe/testimonials';
server.js
const express = require('express');
const cors = require('cors');
const path = require('path');
const axios = require('axios');
const app = express();
const port = process.env.PORT || 80;
app.use(cors());
app.use(express.static('public'));
const API_BASE_URL = 'https://api.frontendexpert.io/api/fe/testimonials';
async function fetchTestimonials(limit = 5, after = 0) {
const testimonialUrl = new URL(API_BASE_URL);
testimonialUrl.searchParams.set('limit', limit);
// testimonialUrl.searchParams.set('after', after);
try {
const testimonials = await axios.get(testimonialUrl);
// console.log(testimonials);
return testimonials.data;
} catch (error) {
console.log(error);
return error;
}
}
app.get('/testimonials', async function (req, res) {
const testimonials = await fetchTestimonials(5, 10);
console.log(testimonials);
res.json(testimonials);
});
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
app.listen(port, function () {
console.log('Server is running on port', port);
});
So on the client console, I am getting a log of raw HTTP response and not the actual JSON. On the express server function, I am getting the exact response. Don't know what is missing.
const testimonials = await fetch('/testimonials');
console.log(testimonials);
I am not able to debug or figure out why my request is logging raw HTTP response
Well, the first step would be to read the documentation for fetch:
Return value: A Promise that resolves to a Response object.
fetch returns a Response object wrapped in a promise.
You're unwrapping it with await and then logging the Response object.
It has various methods on it (such as the json method to wait for the body data to arrive and process it in various ways.
For example, if you want to get the JSON representation of the response body, you can do the following:
const response = await fetch('/testimonials');
const testimonials = await response.json()
console.log(testimonials);

Axios and expressJs request debugging for external HTTP request

My use case or problem arising might be simple. I am not able to debug or figure out why my request is logging Pending promise. Let me kick in all relevant code and we can talk then
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Scroll</title>
<script src="./infiniteScroll.js" defer></script>
</head>
<body>
<div id="testimonial-container"></div>
</body>
</html>
infiniteScroll.js
async function fetchAndAppendTestimonials(limit = 5, after = 0) {
const testimonialsResponse = await fetch('/testimonials');
const testimonials = testimonialsResponse.json();
console.log(testimonials);
}
fetchAndAppendTestimonials(5, 0);
I starting adding server.js incrementally so that I can bypass CORS to call the external API - 'https://api.frontendexpert.io/api/fe/testimonials';
server.js
const express = require('express');
const cors = require('cors');
const path = require('path');
const axios = require('axios');
const app = express();
const port = process.env.PORT || 80;
app.use(cors());
app.use(express.static('public'));
const API_BASE_URL = 'https://api.frontendexpert.io/api/fe/testimonials';
async function fetchTestimonials(limit = 5, after = 0) {
const testimonialUrl = new URL(API_BASE_URL);
testimonialUrl.searchParams.set('limit', limit);
testimonialUrl.searchParams.set('after', after);
try {
const testimonials = await axios.get(API_BASE_URL);
return testimonials.data;
} catch (error) {
console.log(error);
return error;
}
}
app.get('/testimonials', function (req, res) {
const testimonials = fetchTestimonials(5, 0);
console.log('testimonials', testimonials);
res.json(testimonials);
});
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
app.listen(port, function () {
console.log('Server is running on port', port);
});
This is the entire app (w/o package.json and other meta files) so far and what I don't understand is that inside server.js file and fetchTestimonials function, the testimonials returned are Promise { <pending> }. This is evident from the console.log I have after the function call.
Can anyone correct this so that I can return a JSON response back to my client side infiniteScroll.js file?
Tangential but if someone, could add if this is the best approach to allow CORS would be great.
You don't seem to be awaiting fetchTestimonials inside your /testimonials route. By making your route handler async, you can solve the Promise {<pending>}
app.get('/testimonials', async function (req, res) {
try {
const testimonials = await fetchTestimonials(5, 0);
console.log('testimonials', testimonials);
res.json(testimonials);
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal Server Error' });
}
});

How can I send a POST request to display a message to an html file using axios?

I'm using the weatherstack API and want to send the current temperature of a given city to a simple form in html using the POST method in express (or axios, if possible).
I tried to use the GET method in axios to consume the API and the POST method in express to send the result once the user enters the city they want in the search bar. The code is the following:
app.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const axios = require('axios');
const access_key = '...'
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// Successful GET in the console
// axios.get(`http://api.weatherstack.com/current?access_key=${access_key}&query=Dallas`)
// .then(response => {
// const apiResponse = response.data;
// console.log(`Current temperature in ${apiResponse.location.name} is ${apiResponse.current.temperature}℃`);
// }).catch(error => {
// console.log(error);
// });
// ----The problem-------
app.post('/', async function (req, res) {
const{response} = await axios(`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`)
res.send(`<p>Current temperature in ${req.body.cityName} is ${response.current.temperature} ℃</p>
<a href = '/'>Back</a>`)
});
//------------------------
app.listen({port: 4000}, () => {
console.log("Server running on localhost:4000");
});
The website
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weatherstack</title>
</head>
<body>
<form action="/" method="post">
<p>Inform the city</p>
<input name="cityName">
<button type="submit">Send</button>
</form>
</body>
</html>
But when I run the server I get this error:
How can I solve that?
Axios return the AxiosResponse object.
export interface AxiosResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
config: AxiosRequestConfig<D>;
request?: any;
}
the content of your response is within the data object.
const { data } = await axios(
`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`
);
res.send(
`<p>Current temperature in ${req.body.cityName} is ${data.current.temperature} ℃</p><a href = '/'>Back</a>`
)
Or
const response = await axios(
`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`
);
res.send(
`<p>Current temperature in ${req.body.cityName} is ${response.data.current.temperature} ℃</p><a href = '/'>Back</a>`
)
I tested this code, and it works fine.

How to send data from Node js server to client side?

I currently set up a node server which gets some data submitted from a html page and uses it to fetch data from an API. now I would like to display this data in a graphic format to a new html page (or even the same if possible).
In order to do this I think I should first send the data to the client side js. So that it gets the data to create the graph onto the new html page. But how would I do this? I tried to look for some examples unsuccessfully.
Here's a failing attempt at this (I omitted some code that I think wasn't influencial):
//server (Node JS)
const app = express();
app.use(express.json());
app.use(express.urlencoded( {extended: true} ));
const port = process.env.PORT || 8080;
let values;
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
async function fillArrays (from, to) {
...
}
const fetchData = async () => {
...
values = ...;
}
app.post('/input', async function(req,res){
await fillArrays(req.body.a, req.body.b);
console.log("End");
res.sendFile(path.join(__dirname, '/graph.html'));
res.json(await fetchData());
});
app.listen(port);
console.log('Server started at http://localhost:' + port);
graph.html:
<head>
<script src='https://cdn.plot.ly/plotly-2.14.0.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js'></script>
<script type="text/javascript" src="chart.js"></script>
</head>
<body>
<div id='myDiv'></div>
</body>
chart.js :
let dataset;
//attempt at getting data from server side
const promise = fetch('/input');
promise.then(response => {
if(!response.ok){
console.error(response)
} else {
return console.log(response);
}
}).then(result => {
dataset = result;
})
let range1 = Math.min(dataset[0]);
let range2 = Math.max(dataset[0]);
var trace = {
...
}
var data = trace;
var layout = {
...
};
Plotly.newPlot('myDiv', data, layout);

How to send 'text/event-stream' data from express.js?

Trying to get a basic server-sent-event working with express.js on server side:
index.js:
const app = require('express')();
const index_html = require('path').join(__dirname, 'index.html');
app.get('/', (req, res) =>
{
res.sendFile(index_html);
});
app.get('/data', (req, res) =>
{
res.header('Cache-Control', 'no-cache');
res.header('Content-Type', 'text/event-stream');
setInterval(() =>
{
res.write(new Date().toISOString() + '\n\n');
}, 1000);
});
app.listen('7000');
index.html:
<!doctype html>
<head>
<title>Hello World</title>
</head>
<body>
<h1 id='result'>No Data Yet</h1>
<script>
var source = new EventSource('data');
source.onmessage = function(event)
{
console.log('invoked');
document.getElementById('result').innerHTML = event.data + '<br>';
};
</script>
</body>
The source.onmessage never triggers.
Server side events need to send data in a particular (text) format, specifically, to send data, you need a line of text in the format
data: text to send goes here
other types of data in a single event can be type, id, and retry
any line that doesn't start with
data:
type:
id:
retry:
is ignored, hence why you were not getting any events
simple change
setInterval(() =>
{
res.write('data: ' + new Date().toISOString() + '\n\n');
}, 1000);
Though, I'd write it like
setInterval(() => res.write(`data: ${new Date().toISOString()}\n\n`), 1000);
Further reading MDN documentation

Categories