Reputation: 788
I have created a react front end and a node.js API for jobs. The react front end displays jobs that I may be interested in and gives each job a button that says Download Cover Letter. When clicked, this button sends an axios POST request to my node.js API that then takes the request body, and creates a personalized cover letter for me that I can use to apply to jobs. My issue is that the node.js API seems to be doing it's job, however my react application does not download my cover letter to my local machine. I am a bit confused as to why it is not working, as I believe my response headers in my node API is correct.
Here is my react code:
import React from 'react';
import axios from 'axios';
const Job = (props) => {
const onClickHandler = async () => {
try {
const payload = JSON.stringify({"position": props.position,"company": props.company,"fileTitle": "Ryan_Test"});
const config = {
method: 'post',
// url: 'http://test-with-nedal.herokuapp.com/cover-letter',
url: 'http://localhost:1234/cover-letter',
headers: {
'Content-Type': 'application/json'
},
data : payload
};
const { data } = await axios(config)
//console.log(data);
} catch (err) {
console.log(err);
}
}
return (
<div className="col-sm-4">
<div className="card my-3">
<div className="card-body">
<h5 className="card-title">{props.position}</h5>
<h6 className="card-subtitle mb-2 text-muted">{props.company}</h6>
<p className="card-text">{props.description.substring(0, 100)}...</p>
<a href="#" className="btn btn-primary">View Job</a>
</div>
<div className="d-flex justify-content-end">
<button onClick={onClickHandler} className="btn btn-success">Download Cover Letter</button>
<span>Found on <span style={{color: 'green', paddingRight: '10px'}}>{props.poster}</span></span>
</div>
</div>
</div>
)
}
export default Job;
Here is my API endpoint in Node:
const express = require('express');
const dotenv = require('dotenv');
const dateFormat = require('./utils/dateFormat');
const cors = require('cors');
const app = express();
dotenv.config();
app.use(cors());
app.use(express.json());
async function generatePdf(html) {
const puppeteer = require("puppeteer");
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
headless: true
});
const page = await browser.newPage();
await page.goto(`data:text/html,${html}`, {
waitUntil: 'networkidle0'
});
const options = {
format: 'A4',
margin: { top: "60px", bottom: "60px", left: "15px", right: "15px" },
printBackground: true,
}
const pdf = await page.pdf(options);
await browser.close();
return pdf;
}
app.post('/cover-letter', async (req, res) => {
console.log(req.body);
const {position, company, fileTitle} = req.body;
const date = dateFormat(new Date());
const coverLetter = `Way too long to include in a code snippet, but pretend a cover letter HTML is here that uses ${position} and ${company}`;
const pdfBuffer = await generatePdf(coverLetter);
const fileName = `attachment; filename=\"${fileTitle}.pdf\"`;
res.setHeader("Content-Type", "application/octet-stream");
//res.setHeader("Content-Disposition","inline; filename=\"test_resume_company_name.pdf\"");
res.setHeader('Content-Disposition', `attachment; filename=\"test.pdf\"`);
res.status(200).send(pdfBuffer);
});
app.listen(process.env.PORT, () => {
console.log(`Listening on port ${process.env.PORT}...`)
})
Upvotes: 0
Views: 572
Reputation: 106
It seems that you are not using the returned data from your API. I think you should try to change your button to an anchor and add the download attribute like this:
<a href={file} className="btn btn-success" download="file_name">Download Cover Letter</a>
And generate your file on a useEffect as soon as the page loads to reference on your button.
Upvotes: 1