How to Preview and Download HTML Returned from an API Using React and Vue
This article explains how to fetch an HTML string from an API and display it either via an iframe or by rendering the HTML directly in React or Vue, and provides multiple download options—including saving the raw HTML, capturing an image with html2canvas, and generating a PDF using jsPDF.
When a button click triggers a request to an endpoint that returns raw HTML, the goal is to preview that HTML in the browser and offer download options for the source file, an image, or a PDF.
There are two simple ways to render the returned HTML: embed it in an iframe or fetch the HTML string and render it directly using framework‑specific APIs such as v-html in Vue or dangerouslySetInnerHTML in React.
Iframe method (React)
const Component = () => {
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
return (
);
};Iframe method (Vue)
<template>
<iframe :style="{width: '100%', height: '100%'}" :src="url"></iframe>
</template>
<script>
export default {
data() {
return { url: 'http://127.0.0.1:5500/src/pages/flex/IterableEvents/' };
}
};
</script>Fetch‑and‑render method (React)
const Component = () => {
const [htmlContent, setHtmlContent] = useState('');
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
useEffect(() => {
fetch(url)
.then(r => r.text())
.then(data => setHtmlContent(data))
.catch(err => console.error('Error fetching HTML:', err));
}, []);
return (
);
};Fetch‑and‑render method (Vue)
<template>
<div v-html="htmlContent" :style="{ width: '100%' }"></div>
</template>
<script>
export default {
data() { return { htmlContent: '' }; },
created() {
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
fetch(url)
.then(r => r.text())
.then(data => { this.htmlContent = data; })
.catch(err => console.error('Error fetching HTML:', err));
}
};
</script>Downloading the raw HTML file can be done by creating an a element with the URL and programmatically clicking it. This works only when the endpoint is not cross‑origin.
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
const downLoad = async () => {
try {
const link = document.createElement('a');
link.href = url;
link.click();
} catch (error) {
message.error('Download failed');
}
};To capture the page as an image, install html2canvas and render the iframe (or any DOM element) to a canvas, then download the canvas as a PNG.
import html2canvas from 'html2canvas';
const Component = () => {
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
const downLoad = async () => {
try {
const iframe = document.getElementById('myPage');
const targetHtml = iframe?.contentDocument || iframe?.contentWindow?.document;
html2canvas(targetHtml, { scale: 1, useCORS: true }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = imgData;
link.download = 'page.png';
link.click();
});
} catch (error) {
message.error('Download failed');
}
};
return (
);
};The same approach can be applied to a regular DOM element by obtaining it with document.getElementById and passing it to html2canvas .
const targetHtml = document.getElementById('myPage');
html2canvas(targetHtml, { scale: 1, useCORS: true }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = imgData;
link.download = 'page.png';
link.click();
});Generating a PDF combines html2canvas with jsPDF . First capture the page as an image, then add the image to a PDF document, handling pagination if the content exceeds one page.
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
const Component = () => {
const [htmlContent, setHtmlContent] = useState('');
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
const downLoad = async () => {
try {
const targetHtml = document.getElementById('myPage');
const doc = new jsPDF();
const canvas = await html2canvas(targetHtml, { scale: 1, useCORS: true });
const imgData = canvas.toDataURL('image/png');
const imgWidth = 210; // A4 width in mm
const pageHeight = 295; // A4 height in mm
const imgHeight = (canvas.height * imgWidth) / canvas.width;
let heightLeft = imgHeight;
let position = 0;
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save('webpage.pdf');
} catch (error) {
console.error('Download failed:', error);
}
};
useEffect(() => {
fetch(url)
.then(r => r.text())
.then(data => setHtmlContent(data))
.catch(err => console.error('Error fetching HTML:', err));
}, []);
return (
);
};The Vue counterpart follows the same logic, using ref for the DOM element and the same html2canvas + jsPDF workflow.
<template>
<div :style="{ width: '100%', height: '100%', overflow: 'auto' }">
<div v-html="htmlContent" :style="{ width: '100%' }" ref="myPage"></div>
<button @click="downLoad">Download as PDF</button>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
export default {
setup() {
const htmlContent = ref('');
const myPage = ref(null);
const url = "http://127.0.0.1:5500/src/pages/flex/IterableEvents/";
const downLoad = async () => {
try {
const targetHtml = myPage.value;
const doc = new jsPDF();
const canvas = await html2canvas(targetHtml, { scale: 1, useCORS: true });
const imgData = canvas.toDataURL('image/png');
const imgWidth = 210;
const pageHeight = 295;
const imgHeight = (canvas.height * imgWidth) / canvas.width;
let heightLeft = imgHeight;
let position = 0;
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save('webpage.pdf');
} catch (error) {
console.error('Download failed:', error);
}
};
onMounted(() => {
fetch(url)
.then(r => r.text())
.then(data => { htmlContent.value = data; })
.catch(err => console.error('Error fetching HTML:', err));
});
return { htmlContent, myPage, downLoad };
}
};
</script>In summary, the simplest solution for previewing the returned HTML is to embed it in an iframe . For more flexible rendering, fetch the HTML and inject it with framework‑specific directives, and use html2canvas together with jsPDF to provide image or PDF download capabilities, keeping in mind cross‑origin restrictions.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.