I create a PDF in ReactJS using react-pdf/renderer and download it using file-saver.
Here is my code that creates the PDF
and downloads it:
const LazyDownloadPDFButton = (number, date, totalHours, formattedHours) => (
<Button
className={classes.download}
onClick={
async () => {
const doc = <InvoicePDF number={number} date={date} totalHours={totalHours} formattedHours={formattedHours} />
const asPdf = pdf()
asPdf.updateContainer(doc)
const blob = await asPdf.toBlob()
saveAs(blob, `PDF${number}.pdf`)
}}>
Download
</Button>
)
where InvoicePDF
is a separate component that renders the PDF
pages with the necessary arguments, as in react-pdf/renderer
documentation page.
Before download the actual PDF
I have to merge it with another existing PDF
that will be choose from computer drive. To do that I have the next code snippet:
fileRef = useRef()
<Button onClick={() => fileRef.current.click()}>
Upload file
<input
ref={fileRef}
type='file'
style={{ display: 'none' }}
/>
</Button>
Which returns me the details of the file.
I tried to updateContainer
with this selected file, but there are errors.
How this new file should be merged with the InvoicePDF
that is created?
In the meantime, I tried to create my last blob
from arrayBuffers
like this:
This is the function that concatenates the created PDF
with the selected PDF
and it returns the correct sum.
function concatArrayBuffers(buffer1, buffer2) {
if (!buffer1) {
return buffer2;
} else if (!buffer2) {
return buffer1;
}
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
};
And my method now have a finalBlob
that is created with arrayBuffers
but the problem is that the resulted PDF
will always contain just the content of the second arrayBuffer (which is either the selected pdf or the created pdf)
const LazyDownloadPDFButton = (number, date, totalHours, formattedHours) => (
<Button
className={classes.download}
onClick={
async () => {
const doc = <InvoicePDF number={number} date={date} totalHours={totalHours} formattedHours={formattedHours} />
const asPdf = pdf()
asPdf.updateContainer(doc)
const initialBlob = await new Blob([fileRef.current.files[0]], { type: 'application/pdf' }).arrayBuffer()
const blob = await (await asPdf.toBlob()).arrayBuffer()
const finalArrayBuffer = concatArrayBuffers(initialBlob, blob)
const finalBlob = new Blob([finalArrayBuffer], { type: 'application/pdf' })
saveAs(finalBlob, `PDF${number}.pdf`)
}}
>
Download
</Button>
)