skip to Main Content

I’ve Base64 string and want to convert into pdf. my function work for small base64 string like text Images, emojis and all but when I add images more than 50kb(not sure) base64 string then my function can’t convert it base64 string to pdf.

I’ve tried many previous Stack Overflow solutions, but nothing seems to work.

const ConverToPdf = (b64) =>{
    const base64String = b64
    const byteCharacters = window.atob(base64String);
    const byteArrays = [];

    for (let offset = 0; offset < byteCharacters.length; offset += 512) {
      const slice = byteCharacters.slice(offset, offset + 512);

      const byteNumbers = new Array(slice.length);
      for (let i = 0; i < slice.length; i++) {
        byteNumbers[i] = slice.charCodeAt(i);
      }

      const byteArray = new Uint8Array(byteNumbers);
      byteArrays.push(byteArray);
    }

    const pdfFile = new Blob(byteArrays, { type: 'application/pdf' });
    const pdfUrl = URL.createObjectURL(pdfFile);

    // Create a download link
    const downloadLink = document.createElement('a');
    downloadLink.href = pdfUrl;
    downloadLink.download = 'converted.pdf';

    // Simulate click to trigger the download
    downloadLink.click();

    // Cleanup
    URL.revokeObjectURL(pdfUrl);
    document.body.removeChild(downloadLink);
}

2

Answers


  1. Chosen as BEST ANSWER

    using pdf-lib library I can covert any size of base64 to pdf but wanted to solve this witout any library

    import { PDFDocument } from "pdf-lib";
    export const makeDownloadToPDF = async (b64, height, width) => {
      
        try {
          const binaryString = window.atob(b64);
      
          const pdfDoc = await PDFDocument.create();
          const imageBytes = Uint8Array.from([...binaryString].map((char) => char.charCodeAt(0)));
      
          const image = await pdfDoc.embedPng(imageBytes);
          const page = pdfDoc.addPage([image.width, image.height]);
          page.drawImage(image, {
            x: 0,
            y: 0,
            width: image.width,
            height: image.height,
          });
      
          const pdfBytes = await pdfDoc.save();
      
          const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
      
          // Create a download link
          const downloadLink = document.createElement('a');
          downloadLink.href = URL.createObjectURL(pdfBlob);
          downloadLink.download = 'converted.pdf';
      
          // Simulate click to trigger the download
          document.body.appendChild(downloadLink);
          downloadLink.click();
      
          // Cleanup
          URL.revokeObjectURL(downloadLink.href);
          document.body.removeChild(downloadLink);
        } catch (error) {
          console.error('Error converting image to PDF:', error);
        }
    }
    

  2. You are running into a known issue with window.atob() in JavaScript. This function fails for base64 strings that are larger than 65536 bytes. This is because it tries to allocate a single continuous block of memory for the decoded string and that size of allocation may not always be possible, especially for larger base64 strings.

    A good alternative is to use the TextEncoder and TextDecoder APIs to perform the conversion, these APIs are much more reliable for larger strings.

    Here’s how you can modify your function:

    const ConverToPdf = (b64) =>{
        const binaryString = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
        
        const byteArrays = [];
    
        for (let offset = 0; offset < binaryString.length; offset += 512) {
          const slice = binaryString.slice(offset, offset + 512);
          byteArrays.push(slice);
        }
    
        const pdfFile = new Blob(byteArrays, { type: 'application/pdf' });
        const pdfUrl = URL.createObjectURL(pdfFile);
    
        // Create a download link
        const downloadLink = document.createElement('a');
        downloadLink.href = pdfUrl;
        downloadLink.download = 'converted.pdf';
    
        // Simulate click to trigger the download
        document.body.appendChild(downloadLink);  // Append the link to the body before click
        downloadLink.click();
    
        // Cleanup
        URL.revokeObjectURL(pdfUrl);
        document.body.removeChild(downloadLink);
    }
    

    This function should solve the issue of window.atob() failing for larger base64 strings. The TextEncoder and TextDecoder APIs provide much better performance and reliability for large strings, and should be preferred in these cases.

    This function also has a correction in the creation and triggering of the download link. You should append the link to the document’s body before simulating the click. Once the click is simulated and the download is triggered, you can then remove the link from the body.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search