Создать PDF из HTML в div с помощью Javascript

У меня есть следующий код html:

<!DOCTYPE html>
<html>
    <body>
        <p>don't print this to pdf</p>
        <div id="pdf">
            <p><font size="3" color="red">print this to pdf</font></p>
        </div>
    </body>
</html>

Все, что я хочу сделать, это распечатать в pdf все, что находится в div, с идентификатором "pdf". Это должно быть сделано с использованием JavaScript. Затем документ "pdf" должен быть автоматически загружен с именем файла "foobar.pdf"

Я использую jspdf для этого, но единственной функцией, которую он имеет, является "текст", который принимает только строковые значения. Я хочу отправить HTML в jspdf, а не текст.

Ответ 1

jsPDF может использовать плагины. Чтобы включить его для печати HTML, вы должны включить определенные плагины и, следовательно, должны сделать следующее:

  • Перейдите в https://github.com/MrRio/jsPDF и загрузите последнюю версию.
  • Включите следующие сценарии в свой проект:
    • jspdf.js
    • jspdf.plugin.from_html.js
    • jspdf.plugin.split_text_to_size.js
    • jspdf.plugin.standard_fonts_metrics.js

Если вы хотите игнорировать определенные элементы, вы должны пометить их идентификатором, который затем можно игнорировать в специальном обработчике jsPDF. Поэтому ваш HTML-код должен выглядеть так:

<!DOCTYPE html>
<html>
  <body>
    <p id="ignorePDF">don't print this to pdf</p>
    <div>
      <p><font size="3" color="red">print this to pdf</font></p>
    </div>
  </body>
</html>

Затем вы используете следующий код JavaScript, чтобы открыть созданный PDF файл в PopUp:

var doc = new jsPDF();          
var elementHandler = {
  '#ignorePDF': function (element, renderer) {
    return true;
  }
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
    source,
    15,
    15,
    {
      'width': 180,'elementHandlers': elementHandler
    });

doc.output("dataurlnewwindow");

Для меня это создало хороший и аккуратный PDF файл, который включал только строку 'print this to pdf'.

Обратите внимание, что обработчики специальных элементов обрабатывают только идентификаторы в текущей версии, что также указано в проблеме GitHub. В нем указано:

Поскольку соответствие выполняется с каждым элементом в дереве node, я хотел сделать это как можно быстрее. В этом случае это означало: "Идентификаторы только элементов совпадают" Идентификаторы элементов по-прежнему выполняются в стиле jQuery "#id", но это не означает, что поддерживаются все селектора jQuery.

Поэтому замена "#ignorePDF" на селектора классов типа ".ignorePDF" не сработала для меня. Вместо этого вам придется добавить один и тот же обработчик для каждого элемента, который вы хотите игнорировать, например:

var elementHandler = {
  '#ignoreElement': function (element, renderer) {
    return true;
  },
  '#anotherIdToBeIgnored': function (element, renderer) {
    return true;
  }
};

Из examples также указано, что можно выбрать теги типа 'a' или 'li'. Это может быть немного ограничено для большинства случаев:

Мы поддерживаем специальные обработчики элементов. Зарегистрируйте их с помощью jQuery-стиля ID для идентификатора или имени node. ( "#AID", "div", "span" и т.д.) Нет поддержки для других типов селекторов (класс, соединение) в настоящее время.

Очень важно добавить, что вы теряете всю информацию о стиле (CSS). К счастью, jsPDF умеет красиво форматировать h1, h2, h3 и т.д., Что было достаточно для моих целей. Дополнительно он будет печатать текст только в текстовых узлах, а это значит, что он не будет печатать значения текстовых областей и т.п. Пример:

<body>
  <ul>
    <!-- This is printed as the element contains a textnode -->        
    <li>Print me!</li>
  </ul>
  <div>
    <!-- This is not printed because jsPDF doesn't deal with the value attribute -->
    <input type="textarea" value="Please print me, too!">
  </div>
</body>

Ответ 2

Это простое решение. Это работает для меня. Вы можете использовать концепцию печати javascript и просто сохранить это как pdf.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
        $("#btnPrint").live("click", function () {
            var divContents = $("#dvContainer").html();
            var printWindow = window.open('', '', 'height=400,width=800');
            printWindow.document.write('<html><head><title>DIV Contents</title>');
            printWindow.document.write('</head><body >');
            printWindow.document.write(divContents);
            printWindow.document.write('</body></html>');
            printWindow.document.close();
            printWindow.print();
        });
    </script>
</head>
<body>
    <form id="form1">
    <div id="dvContainer">
        This content needs to be printed.
    </div>
    <input type="button" value="Print Div Contents" id="btnPrint" />
    </form>
</body>
</html>

Ответ 3

Вы можете использовать autoPrint() и установить вывод на "dataurlnewwindow" следующим образом:

function printPDF() {
    var printDoc = new jsPDF();
    printDoc.fromHTML($('#pdf').get(0), 10, 10, {'width': 180});
    printDoc.autoPrint();
    printDoc.output("dataurlnewwindow"); // this opens a new popup,  after this the PDF opens the print window view but there are browser inconsistencies with how this is handled
}

Ответ 4

Как уже упоминалось, вы должны использовать jsPDF и html2canvas. Я также нашел функцию внутри проблем jsPDF, которая автоматически разбивает ваш PDF на несколько страниц (источники)

function makePDF() {

    var quotes = document.getElementById('container-fluid');

    html2canvas(quotes, {
        onrendered: function(canvas) {

        //! MAKE YOUR PDF
        var pdf = new jsPDF('p', 'pt', 'letter');

        for (var i = 0; i <= quotes.clientHeight/980; i++) {
            //! This is all just html2canvas stuff
            var srcImg  = canvas;
            var sX      = 0;
            var sY      = 980*i; // start 980 pixels down for every new page
            var sWidth  = 900;
            var sHeight = 980;
            var dX      = 0;
            var dY      = 0;
            var dWidth  = 900;
            var dHeight = 980;

            window.onePageCanvas = document.createElement("canvas");
            onePageCanvas.setAttribute('width', 900);
            onePageCanvas.setAttribute('height', 980);
            var ctx = onePageCanvas.getContext('2d');
            // details on this usage of this function: 
            // https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
            ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);

            // document.body.appendChild(canvas);
            var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);

            var width         = onePageCanvas.width;
            var height        = onePageCanvas.clientHeight;

            //! If we're on anything other than the first page,
            // add another page
            if (i > 0) {
                pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
            }
            //! now we declare that we're working on that page
            pdf.setPage(i+1);
            //! now we add content to that page!
            pdf.addImage(canvasDataURL, 'PNG', 20, 40, (width*.62), (height*.62));

        }
        //! after the for loop is finished running, we save the pdf.
        pdf.save('test.pdf');
    }
  });
}

Ответ 5

если вам нужно загрузить PDF с определенной страницы, просто добавьте кнопку, подобную этой

<h4 onclick="window.print();"> Print </h4>

используйте window.print(), чтобы напечатать всю страницу, а не просто div

Ответ 6

Одним из способов является использование функции window.print(). Который не требует никакой библиотеки

Pros

1. Никакой внешней библиотеки не требуется.

2. Мы можем печатать только отдельные части тела.

3. Никаких конфликтов и проблем.

4.Core html/js функциональность

---Simply добавить код ниже

CSS для

@media print {
        body * {
            visibility: hidden; // part to hide at the time of print
            -webkit-print-color-adjust: exact !important; // not necessary use         
               if colors not visible
        }

        #printBtn {
            visibility: hidden !important; // To hide 
        }

        #page-wrapper * {
            visibility: visible; // Print only required part
            text-align: left;
            -webkit-print-color-adjust: exact !important;
        }
    }

JS-код - вызов функции bewlow при нажатии btn

$scope.printWindow = function () {
  window.print()
}

Примечание: используйте! Важное в каждом объекте CSS

Пример -

.legend  {
  background: #9DD2E2 !important;
}

Ответ 7

Если вы хотите экспортировать таблицу, вы можете взглянуть на этот пример экспорта, предоставленный виджетами Shield UI Grid.

Это делается путем расширения конфигурации следующим образом:

...
exportOptions: {
    proxy: "/filesaver/save",
    pdf: {
        fileName: "shieldui-export",
        author: "John Smith",
        dataSource: {
            data: gridData
        },
        readDataSource: true,
        header: {
            cells: [
                { field: "id", title: "ID", width: 50 },
                { field: "name", title: "Person Name", width: 100 },
                { field: "company", title: "Company Name", width: 100 },
                { field: "email", title: "Email Address" }
            ]
        }
    }
}
...

Ответ 8

я использую jspdf и html2canvas для рендеринга CSS и экспортирую содержимое определенного div, так как это мой код

$(document).ready(function () {
    let btn=$('#c-oreder-preview');
    btn.text('download');
    btn.on('click',()=> {

        $('#c-invoice').modal('show');
        setTimeout(function () {
            html2canvas(document.querySelector("#c-print")).then(canvas => {
                //$("#previewBeforeDownload").html(canvas);
                var imgData = canvas.toDataURL("image/jpeg",1);
                var pdf = new jsPDF("p", "mm", "a4");
                var pageWidth = pdf.internal.pageSize.getWidth();
                var pageHeight = pdf.internal.pageSize.getHeight();
                var imageWidth = canvas.width;
                var imageHeight = canvas.height;

                var ratio = imageWidth/imageHeight >= pageWidth/pageHeight ? pageWidth/imageWidth : pageHeight/imageHeight;
                //pdf = new jsPDF(this.state.orientation, undefined, format);
                pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio);
                pdf.save("invoice.pdf");
                //$("#previewBeforeDownload").hide();
                $('#c-invoice').modal('hide');
            });
        },500);

        });
});

Ответ 9

Мне удалось получить jsPDF для печати динамически созданных таблиц из div.

$(document).ready(function() {

        $("#pdfDiv").click(function() {

    var pdf = new jsPDF('p','pt','letter');
    var specialElementHandlers = {
    '#rentalListCan': function (element, renderer) {
        return true;
        }
    };

    pdf.addHTML($('#rentalListCan').first(), function() {
        pdf.save("caravan.pdf");
    });
    });
});

Отличная работа с Chrome и Firefox... форматирование все взорвано в IE.

Я также включил их:

<script src="js/jspdf.js"></script>
    <script src="js/jspdf.plugin.from_html.js"></script>
    <script src="js/jspdf.plugin.addhtml.js"></script>
    <script src="//mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
    <script src="http://html2canvas.hertzen.com/build/html2canvas.js"></script>
    <script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
    <script type="text/javascript" src="./libs/Blob.js/Blob.js"></script>
    <script type="text/javascript" src="./libs/deflate.js"></script>
    <script type="text/javascript" src="./libs/adler32cs.js/adler32cs.js"></script>

    <script type="text/javascript" src="js/jspdf.plugin.addimage.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.sillysvgrenderer.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.split_text_to_size.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.standard_fonts_metrics.js"></script>

Ответ 10

  • Никаких зависимостей, чистый JS

Это служило мне в течение многих лет:

export default function printDiv({divId, title}) {
  let mywindow = window.open('', 'PRINT', 'height=650,width=900,top=100,left=150');

  mywindow.document.write('<html><head><title>${title}</title>');
  mywindow.document.write('</head><body >');
  mywindow.document.write(document.getElementById(divId).innerHTML);
  mywindow.document.write('</body></html>');

  mywindow.document.close(); // necessary for IE >= 10
  mywindow.focus(); // necessary for IE >= 10*/

  mywindow.print();
  mywindow.close();

  return true;
}

Ответ 11

GrabzIt также поддерживает преобразование HTML в PDF с его библиотекой JavaScript, и если вы вставляете стили CSS в отправляемый HTML-код, он также будет стилизовать его как вы пожелаете.

Вот пример того, как вы могли это сделать:

<script src="grabzit.min.js">
</script>
<script>
var html = document.getElementById('pdf').innerHTML;

GrabzIt("APPLICATION KEY").ConvertHTML(html,
{"format": "pdf"}).Create();
</script>

Ответ 12

Для захвата div в формате PDF вы можете использовать https://grabz.it решение. Он получил JavaScript API, который является простым и гибким и позволит вам захватить содержимое одного HTML-элемента, такого как div или span

Чтобы реализовать это, вам нужно сначала получить ключ и секрет приложения и download (бесплатно) SDK.

И вот пример.

Скажем, у вас есть HTML:

<div id="features">
    <h4>Acme Camera</h4>
    <label>Price</label>$399<br />
    <label>Rating</label>4.5 out of 5
</div>
<p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget
risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at
blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p>

Чтобы захватить то, что находится под идентификатором функции, вам нужно:

//add the sdk
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
//login with your key and secret. 
GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "format": "pdf"}).Create();
</script>

Обратите внимание на target: #feature. #feature - это ваш селектор CSS, как в предыдущем примере. Теперь, когда страница загружена, снимок экрана теперь будет создан в том же месте, что и тег script, который будет содержать все содержимое функций div и ничего больше.

Другими настройками и настройками вы можете воспользоваться механизм div-screenshot, пожалуйста, проверьте их здесь

Ответ 13

Используйте pdfMake.js и этот список.

(Я нашел Gist здесь вместе со ссылкой на пакет html-to-pdfmake, который я пока не использовал.)

После npm install pdfmake и сохранения Gist в htmlToPdf.js я использую его так:

const pdfMakeX = require('pdfmake/build/pdfmake.js');
const pdfFontsX = require('pdfmake-unicode/dist/pdfmake-unicode.js');
pdfMakeX.vfs = pdfFontsX.pdfMake.vfs;
import * as pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdf from './htmlToPdf.js';

var docDef = htmlToPdf('<b>Sample</b>');
pdfMake.createPdf({content:docDef}).download('sample.pdf');

Замечания:

  • Мой вариант использования - создать соответствующий html из документа уценки (с помощью markdown-it), а затем сгенерировать pdf и загрузить его двоичный контент (который я могу получить с помощью функции pdfMake getBuffer()). все из браузера. Сгенерированный PDF файл оказывается лучше для этого вида HTML, чем с другими решениями, которые я пробовал.
  • Я недоволен результатами, которые я получил из jsPDF.fromHTML(), предложенного в принятом ответе, поскольку это решение легко спутать со специальными символами в моем HTML, которые, по-видимому, интерпретируются как своего рода разметка и полностью портят полученный PDF.
  • Использование решений на основе холста (например, устаревшей функции jsPDF.from_html(), которую не следует путать с функцией из принятого ответа) - не вариант для меня, поскольку я хочу, чтобы текст в сгенерированном PDF файле можно было вставлять, тогда как решения на основе холста генерируют растровое изображение на основе PDF.
  • Конвертеры прямой уценки в pdf, такие как md-to-pdf, предназначены только для сервера и не будут работать для меня.
  • Использование функции печати браузера не будет работать для меня, так как я не хочу отображать сгенерированный PDF, но загружать его двоичный контент.

Ответ 14

jsPDF обновлен. вот правильный код

var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
doc.addPage();
doc.text(20, 20, 'Do you like that?');
doc.save('Test.pdf');