html2pdf.js icon indicating copy to clipboard operation
html2pdf.js copied to clipboard

Save PDF into local server

Open gcuculi opened this issue 5 years ago • 7 comments

Hi, html2pdf is awesome!

Congrats for this solution!

My html content is huge, so I slice into parts avoiding canvas size limitations. :D

let fileName = "evaluation_xxx.pdf";

// Assuming "pages" is an array of HTML elements or strings that are separate pages:

let pages = [];
$('.evaluation-page-template.page').each(function () {
      pages.push($(this)[0]);
});

// Generate the PDF.
let worker = html2pdf().from(pages[0]).set({
      margin: 0,
      filename: fileName,
      html2canvas: { scale: 2 },
      jsPDF: {orientation: 'portrait', unit: 'pt', format: 'a4', compressPDF: true}
}).toPdf();

pages.slice(1).forEach(function (page) {
      worker = worker.get('pdf').then(function (pdf) {
          pdf.addPage();
      }).from(page).toContainer().toCanvas().toPdf();
});
worker = worker.save();

Can I save PDF file into server instead of download it? Maybe with some upload API to send to server? Can you help me?

Thanks!!!

gcuculi avatar Dec 11 '19 13:12 gcuculi

I've also been trying to solve the same problem. I've been trying to capture the the exact point at which the PDF is generated so I can post it to the server from there.

qlint avatar Dec 20 '19 07:12 qlint

Hi, everyone!!!

Many hours later I figured out using parts of other codes that I found around. My solution:

function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}
// Final file name
let fileName = "evaluation_xxx.pdf";

// Assuming "pages" is an array of HTML elements or strings that are separate pages:
let pages = [];
$('.evaluation-page-template.page').each(function () {
    pages.push($(this)[0]);
});

// Generate the PDF.
let worker = html2pdf().from(pages[0]).set({
    margin: 0,
    filename: fileName,
    html2canvas: { scale: 2 },
    jsPDF: { orientation: 'portrait', unit: 'pt', format: 'a4', compressPDF: true}
}).toPdf();
    
pages.slice(1).forEach(function (page) {
    worker = worker.get('pdf').then(function (pdf) {
        pdf.addPage();
    }).from(page).toContainer().toCanvas().toPdf();
});

worker = worker.output("datauristring").then(function(pdf) {

    const variable_1 = "x";
    const variable_2 = "y";

    const preBlob = dataURItoBlob(pdf);
    const file = new File([preBlob], fileName, {type: 'application/pdf'}); 

    let data = new FormData();
    data.append("variable_1", variable_1);
    data.append("variable_2", variable_2);
    data.append("file", file);

    $.ajax({
        method: 'POST',
        url: "api/uploadPDF.php",
        data: data,
        processData: false,
        contentType: false
    }).success(function (data, textStatus, jqXHR) {
        data = JSON.parse(data);
    }).error(function (jqXHR, textStatus, errorThrown) {
        console.log(errorThrown);
    });

});

PHP code

$file = (isset($_FILES['file']) ? $_FILES['file'] : NULL);

@move_uploaded_file($file['tmp_name'], $filePath . $fileName)

I know html2pdf is recommended to let things in client side, but this solution (save into server feature) is not part of initial scope of this project, so save me a lot of time.

Thanks @eKoopmans for this awesome work.

Merry Christmas and a great new year for all of us!!!

gcuculi avatar Dec 20 '19 12:12 gcuculi

@gcuculi Why need dataURI convert to blob?

html2pdf().set(opt).from(element).toPdf().get('pdf').then(function (pdfObj) {
    const perBlob = pdfObj.output('blob');

    var formData = new FormData();
    formData.append('file', perBlob, opt.filename);
    
});

bidianqing avatar Mar 21 '20 04:03 bidianqing

@gcuculi thanks man u just saved me lol

LhonRafaat avatar May 10 '21 15:05 LhonRafaat

@gcuculi I'm jumping in there late (December 2021) but just wanted to say thank you! This is absolutely brilliant - You are a life saver!

For anyone who might want to allow the user to download the save the pdf too, just add worker.save(); to the end of the .output().then() function and the ajax happens in the background while the user is downloading the file =D

ColedonProjects avatar Dec 24 '21 13:12 ColedonProjects

I can't make it work for me. Is anyone can explain me more the snippet above to help me. I don't understand the FormData part and the AJAX part.

RyanPeyrot avatar Feb 09 '22 13:02 RyanPeyrot

I can't make it work for me. Is anyone can explain me more the snippet above to help me. I don't understand the FormData part and the AJAX part.

I managed to get this working and posted my full explanation for the code here https://github.com/eKoopmans/html2pdf.js/issues/589 hope it helps you.

Chantellelander avatar Sep 07 '22 08:09 Chantellelander