Search code examples
javascriptreactjsjspdfhtml-to-pdf

I want to convert html to pdf. I have problem in jsPDF


I have a HTML element that I want to convert to PDF. I don't want to convert it to an image and then to PDF, but to PDF directly. But the Turkish characters are broken. My export function:

const ExportPDF = (FileName, Component, Size) => {
        Size = Size ?? [1100, 1200]

        var pdf = new jsPDF({
            orientation: '1',
            unit: 'px',
            format: Size,
        })

        var options = {
            callback: (pdf) => {
                pdf.save((FileName ?? "output") + ".pdf");
            },
            x: 10,
            y: 10,
        }

        pdf.html(Component, options)
    }

I am using it like this:

<Button
    fullWidth
    variant="outlined"
    color="info"
    size="large"
    startIcon={<FilePdfBox />}
    onClick={() => {
        const PDFComponent = document.getElementById("pdf-content")
        ExportPDF("output-test", PDFComponent)
    }}
>
    Download as PDF
</Button>

How can I convert it to pdf without garbled characters?

I tried these methods:

        var options =  {
            encoding: 'UTF-8',
            ...
        }
pdf.addFont("../../font/arialuni.ttf", "ArialUnicodeMS", "normal")
pdf.setFont("ArialUnicodeMS")

Solution

  • You need to use a font that supports Turkish characters. Here's how you can add an font to support special Turkish characters in jsPDF

     const ExportPDF = (fileName, component, size) => {
       // Set default size to [1100, 1200] if size is not provided
       size = size || [1100, 1200];
     
       // Load the custom font
       const fontUrl =
      'https://cdnjs.cloudflare.com/ajax/libs/ink/3.1.10/fonts/Roboto/roboto-light-webfont.ttf';
       const fontName = 'Roboto';
       const fontFile = `${fontName}.ttf`;
     
       const loadFont = new Promise((resolve, reject) => {
       if (window.sessionStorage.getItem(fontName)) {
           resolve();
           return;
         }
     
         const xhr = new XMLHttpRequest();
         xhr.open('GET', fontUrl, true);
         xhr.responseType = 'blob';
     
         xhr.onload = () => {
           if (xhr.status === 200) {
             const blob = new Blob([xhr.response], { type: 'application/octet-     stream' });
             const url = URL.createObjectURL(blob);
             const reader = new FileReader();
             reader.readAsDataURL(blob);
             reader.onload = () => {
               const base64 = reader.result.split(',')[1];
               window.sessionStorage.setItem(fontName, base64);
               resolve();
             };
           } else {
             reject(xhr.statusText);
           }
         };
     
         xhr.onerror = () => {
           reject(xhr.statusText);
         };
     
         xhr.send();
       });
     
       loadFont.then(() => {
         // Create a new jsPDF instance
         const doc = new jsPDF({
           orientation: 'portrait',
           unit: 'px',
           format: size,
         });
     
         // Embed the custom font in the PDF
         const fontBase64 = window.sessionStorage.getItem(fontName);
         doc.addFileToVFS(fontFile, fontBase64);
         doc.addFont(fontFile, fontName, 'normal');
     
         // Set the font for the PDF
         doc.setFont(fontName);
     
         // Get the HTML element you want to convert to a PDF
         const element = component;
     
         // Add the HTML element to the PDF
         const options = {
           callback: (pdf) => {
             pdf.save(`${fileName || 'output'}.pdf`);
           },
           x: 10,
           y: 10,
         };
         doc.html(element, options);
       });
     };