Fastify - Sending a PDF from node.js server - node.js

I have an API built on node.js with Fastify.
The server generates a PDF which I'm then trying to send to a client via an API request. However the request I see in Chrome under network shows the type as XHR, despite me having set the content type like so:
const fs = require('fs')
const stream = fs.createReadStream('../test.pdf', 'binary')
reply.header('Content-Type', 'application/pdf')
reply.send(stream).type('application/pdf').code(200)
On the client side, I'm just making a simple POST request and assuming if its a PDF, the browser will just download it.
axios.post('http://127.0.0.1:8080/contract', requestBody)
.then((response: any) => {
setIsSubmitting(false)
})
.catch((error: any) => {
//TODO
});
(Also, the other thought I had was is this actually the correct way to send i.e. with fs.createReadStream - it's just a static file).
Any ideas what I'm doing wrong in the above.

I had the same problem. Found out this is a problem with fastify, you can upgrade to the latest (Today is 3.27.2).
The issue: https://github.com/fastify/fastify/issues/3283
Bug fix: https://github.com/fastify/fastify/pull/3285

Related

How to serve a PDF in Express/Node and download in client button?

I have an Express/Node server with an endpoint to provide the PDF, and a React client that is making a get request to that endpoint.
Currently the PDF is in what I believe is raw pdf binary data string form (obtained from the response of a separate api request), and on the client side I want to click a button in the browser and have the PDF download.
I'm not sure what is needed on the server side and on the client side to successfully trigger
the download on request.
Do I need to convert the binary PDF data to something on the server side first? Or does this get handled on the client side?
And what would be the code to do this?
Server:
const servePDF = async (req, res) => {
const pdfBinary = '%PDF-1.4 %âãÏÓ 2 0 obj <</ColorSpa ......'
~code here to send pdf as response~
}
Client:
const downloadPDF = async () => {
~get request code here, to run onClick of a button, to download file~
}

Post a simple react form - node, axios, nodemailer, backend, postman

I've set up a react form running on http://localhost:3000/about and I've the backend running on port 5000 (localhost:5000). On react's package.json I set up "proxy":"localhost:5000:.
When I use postman and I send the post to localhost:5000/api/contact, the email is sent correctly (I send the data as JSON - name, email and message). Status 200
When I use the react form, the data is well prepared as json but I can't figure out the baseURL to send correctly the method post. status 404. I tried:
localhost:3000/about/api/contact;
localhost:3000/api/contact;
localhost:3000/api.... None works...
FYI
the server is set up with the following middleware and is working ok:
app.use('/api',contactRoute)
the controller is imported and coded as following:
router.post('/contact', (req, res)=>{
const data = req.body;
The React part is not posting correctly with axios and is coded as following:
onSubmit: async (values) => {
//values.preventDefault();
try {
const data = (JSON.stringify(values, null, 2))
setLoader(true);
console.log(data)
await axios.post('/contact', data);
The method post in react is never completed, when I check the console.log of data, is correctly structured as JSON...status 404
use the post parameter in your axois request {port: 5000} then It will use your actual backend port.
By default, axios uses the base path from the URL. So, here when an API request is made.
await axios.post('/contact', data);
It is actually making the post request on localhost:3000 rather than your backend server at localhost:5000. Also, "api" should also be prepended.
One simple way is to use absolute URL which should work.
await axios.post('http://localhost:5000/api/contact', data);

How to fetch mutiple images from express api's into react application?

I am using mern stack to program an application. I used multer package with express for file uploading and uploaded images in a directory in node.js application. Now i want to fetch the image from that directory. How can i do this? I have found
res.sendFile()
but there are cases when i will need to fetch multiple files from server at once. I also have found just sending path from api to react and serving from a folder into react which i don't find secure? how do i go about it?
You should decouple the back end from the front end, which means, separate the express part from the React part and make simple API, express also can serve files as static(search google for static file serving), then call the API from your React App. Just give the React App Image URL like example.com/static/image1.png(<img src={"example.com/static/image1.png"} />)
I ended up using streams for my problem the following snippet might come in handy for some one with similar issue.
const fs = require('fs')
const stream = require('stream')
app.get('path',(req, res) => {
const r = fs.createReadStream('path to file') // or any other way to get a readable stream
const ps = new stream.PassThrough() // <---- this makes a trick with stream error handling
stream.pipeline(
r,
ps, // <---- this makes a trick with stream error handling
(err) => {
if (err) {
console.log(err) // No such file or any other kind of error
return res.sendStatus(400);
}
})
ps.pipe(res) // <---- this makes a trick with stream error handling
});

Making an http request using NodeJS and access the returned cookies

I am querying a remote API using NodeJS. I am currently using Axios to make the request, but I am willing to use another package if required.
Using NodeJS, I make a request to a remote API.
Axios.post("http://remote.api/getCookie")
.then(value => {
console.log(value);
});
The API returns a number of cookies (this can be seen in the spec, and when I test it in a browser). How can I access these cookies from the value returned by Axios.
Just get them from the Set-Cookie header:
Axios.post("http://<url>").then(response => {
const cookies = response.headers["set-cookie"];
// do whatever you want
}
You can then parse the header by yourself or use a library like cookie or set-cookie-parser

Express res.redirect shows content but not downloads

I have and API link what automatically starts downloading file if I follow it in address bar. Let's call it my-third-party-downloading-link-com.
But when in Express framework I set res.redirect(my-third-party-downloading-link-com). I get status code 301 and can see file content in Preview tab in developer tools. But I can't make Browser downloading this file.
My appropriate request handler is following:
downloadFeed(req, res) {
const { jobId, platform, fileName } = req.query;
const host = platform === 'production' ? configs.prodHost :
configs.stageHost;
const downloadLink = `${host}/api/v1/feedfile/${jobId}`;
// I also tried with these headers
// res.setHeader('Content-disposition', 'attachment;
// filename=${fileName}.gz');
// res.setHeader('Content-Type', 'application/x-gzip');
res.redirect(downloadLink)
}
P.S Now, to solve this problem, I build my-third-party-downloading-link-com on back-end, send it with res.end and then:
window.open(**my-third-party-downloading-link-com**, '_blank').
But I don't like this solution. How can I tell browser to start downloading content form this third-party API ?
According to the documentation, you should use res.download() to force a browser to prompt the user for download.
http://expressjs.com/es/api.html#res.download

Resources