Можно ли сохранить HTML-страницу в формате PDF с помощью JavaScript или jquery?

84

Можно ли сохранить HTML-страницу в формате PDF с помощью JavaScript или jquery?

В деталях:

Я создал одну HTML-страницу, содержащую таблицу. Он имеет одну кнопку «Сохранить как PDF». Если пользователь нажимает эту кнопку, эта HTML-страница должна быть преобразована в файл PDF.

Возможно ли использование JavaScript или jquery?

баран
источник
3
Насколько я знаю, Javascript не может создавать PDF-документы.
Кхоа Ле
1
В наши дни многие люди могут печатать в формате PDF. Так что эта функциональность, возможно, не требуется.
Эрик
4
PDF - это текстовый язык. Вам будет сложно найти язык программирования, на котором вы не сможете его сгенерировать.
Квентин
1
возможный ответ здесь: stackoverflow.com/questions/12108806/…
colin

Ответы:

28

Да , используйте jspdf для создания файла PDF.

Затем вы можете превратить его в URI данных и вставить ссылку для скачивания в DOM.

Однако вам нужно будет самостоятельно написать преобразование HTML в PDF.

Просто используйте версии вашей страницы для печати и позвольте пользователю выбрать способ печати страницы.

Изменить: по- видимому, у него минимальная поддержка

Итак, ответ - напишите свой собственный PDF-редактор или попросите существующий PDF-редактор сделать это за вас (на сервере).

Райнос
источник
jspdf выглядят интересно, но демоверсии не работают ни в Firefox 5.0, ни в IE!
Тим Бют
jspdf имеет минимальную поддержку функций, он даже не поддерживает графику. Но если нет системы стилей и рендеринга - это просто полезно для небольших заметок. В противном случае вам также придется написать целое средство визуализации HTML в JS (или обмануть и использовать холст с drawElement, который только что поддерживается в Firefox, я, кажется, помню). Если вы спросите меня, Javascript действительно не подходит для этой строки кода. Возможно, вызов внешнего веб-сервиса - самый простой способ.
Джон Леннарт Осенден,
JavaScript (как язык) полностью зависит от него. JavaScript работает с ограничениями моделей безопасности браузера и API в меньшей степени.
Квентин
4
Я уверен, что кто-то может построить дом из спичек или зубочисток, но, в конце концов, о полноценном компиляторе pdf с поддержкой сшивки, графики, встраивания шрифтов, стилей и полнофункциональных таблиц поиска не может быть и речи. Взгляните на исходный код jspdf - он поддерживает только самые простые теги и никаких словарей поиска. Полноценный компилятор pdf трудно сделать на C ++ или Delphi даже, чистая реализация JS была бы самоубийственной. Есть компании, которые годами работают, продавая только свои компиляторы pdf (например, см. Gnostice). Это не «однострочный».
Джон Леннарт Осенден 01
@JonLennartAasenden Да, у него минимальная поддержка. Вы все еще можете написать PDF-редактор на js, если хотите. Однако это непростая задача. Реализация на чистом JS так же самоубийственна, как C ++ или Delphi. Не притворяйтесь, что JS - гражданин второго сорта.
Raynos 01
15

Я очень легко это сделать с помощью javascript. Надеюсь, этот код будет вам полезен.

Вам понадобится библиотека JSpdf .

<div id="content">
     <h3>Hello, this is a H3 tag</h3>

    <p>a pararaph</p>
</div>
<div id="editor"></div>
<button id="cmd">Generate PDF</button>

<script>
    var doc = new jsPDF();
    var specialElementHandlers = {
        '#editor': function (element, renderer) {
            return true;
        }
    };

    $('#cmd').click(function () {
        doc.fromHTML($('#content').html(), 15, 15, {
            'width': 170,
                'elementHandlers': specialElementHandlers
        });
        doc.save('sample-file.pdf');
    });

    // This code is collected but useful, click below to jsfiddle link.
</script>

ссылка jsfiddle здесь

Блэкджокер
источник
1
изображение не печатается в pdf :( у вас есть решение ??
маэстро Владимир
2
Он не поддерживает работу с несколькими страницами и CSS-стили должным образом.
Dynamic
1
Не поддерживает таблицы :(
Очень понравился
3
Ссылка JSFiddle ведет на страницу 404
Оскар Чемберс
13

Это может быть поздний ответ, но это лучший вариант: https://github.com/eKoopmans/html2pdf

Реализация на чистом javascript. Позволяет указать только один элемент по идентификатору и преобразовать его.

Billcountry
источник
1
Ответить не поздно :). Спасибо
Калян Чавали
7

Вы можете использовать Phantomjs. Загрузите здесь и используйте следующий пример для проверки функции преобразования html-> pdf https://github.com/ariya/phantomjs/blob/master/examples/rasterize.js

Пример кода:

phantomjs.exe examples/rasterize.js http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/xhtml/index.html sample.pdf
Singh1469
источник
Можете ли вы использовать его с javascript вместо утилиты командной строки?
Dynamic
@Dynamic нет, это безголовый браузер, которым можно управлять с помощью javascript. Вы можете указать ему распечатать веб-страницу в PDF с помощью javascript, но реализация не является javascript. Однако я использовал его для этого точного сценария, обернув его в приложение, которое потребляет очередь страниц для печати, и я использую javascript для добавления записей в очередь. Точно так же вы можете обернуть это в сервис. Чтобы контролировать печать, хотя вы находитесь под теми же ограничениями, что и chrome print (например, css и js для создания удобного для печати представления)
Шейн
7

Я использовал jsPDFиdom-to-image библиотеку для экспорта HTML в PDF.

Я публикую здесь как ссылку на кого касается.

$('#downloadPDF').click(function () {
    domtoimage.toPng(document.getElementById('content2'))
      .then(function (blob) {
          var pdf = new jsPDF('l', 'pt', [$('#content2').width(), $('#content2').height()]);
          pdf.addImage(blob, 'PNG', 0, 0, $('#content2').width(), $('#content2').height());
          pdf.save("test.pdf");
      });
});

Демо: https://jsfiddle.net/viethien/md03wb21/27/

Хиен Нгуен
источник
Если я перехожу в адаптивный режим и загружаю PDF-файл, страница PDF-файла не отображается должным образом. Есть ли способ достичь того же результата, что и в режиме рабочего стола, когда я загружаю в адаптивном режиме.
Нэнси
6

Вот как я бы это сделал, это идея не пуленепробиваемая конструкция, вам нужно ее изменить

  • Пользователь нажимает кнопку "Сохранить как PDF".
  • На сервер отправляется вызов с использованием ajax
  • Сервер отвечает URL-адресом PDF-файла, созданного с использованием HTML, я очень успешно использовал Apache FOP
  • Js, обрабатывающий ответ ajax, выполняет location.href, чтобы указать URL-адрес, отправленный JS, и как только этот URL-адрес загружается, он отправляет файл, используя заголовок размещения содержимого в качестве вложения, заставляющего пользователя загрузить файл.
Кумар
источник
2

Конвертировать html в pdf на стороне сервера намного проще и надежнее. Мы используем Google Puppeteer. Он хорошо поддерживается оболочками для любого языка на стороне сервера по вашему выбору. Puppeteer использует Chrome без головы для создания скриншотов и / или файлов PDF. Это избавит вас от головной боли, особенно если вам нужно создать сложные файлы PDF с таблицами, изображениями, графиками, несколькими страницами и т. Д.

https://developers.google.com/web/tools/puppeteer/

Матей Яновчик
источник
2

Есть еще один очень очевидный способ конвертировать HTML в PDf с помощью JavaScript: использовать для этого онлайн-API. Это будет нормально работать, если вам не нужно выполнять преобразование, когда пользователь не в сети.

PdfMage - это один из вариантов, который имеет хороший API и предлагает бесплатные учетные записи. Я уверен, что можно найти много альтернатив (например, здесь )

Для PdfMage API у вас будет что-то вроде этого:

 $.ajax({
    url: "https://pdfmage.org/pdf-api/v1/process",
    type: "POST",
    crossDomain: true,
    data: { Html:"<html><body>Hi there!</body></html>" },
    dataType: "json",
    headers: {
        "X-Api-Key": "your-key-here" // not very secure, but a valid option for non-public domains/intranet
    },
    success: function (response) {
        window.location = response.Data.DownloadUrl;
    },
    error: function (xhr, status) {
        alert("error");
    }
});
Андре Борхес
источник
3
Freehtmltopdf.com, похоже, больше не работает
Зак Сосье
1
К сожалению, PDFMage больше не является бесплатным.
Прометей
1

Да. Например, вы можете использовать решение https://grabz.it .

У него есть Javascript API, который можно использовать по-разному для захвата и управления снимком экрана. Для того , чтобы использовать его в вашем приложении вам нужно будет сначала получить ключ приложения и секрет и скачать бесплатную Javascript SDK.

Итак, давайте посмотрим на простой пример его использования:

//first include the grabzit.min.js library in the web page
<script src="grabzit.min.js"></script>
//include the code below to add the screenshot to the body tag    
<script>
//use secret key to sign in. replace the url.
GrabzIt("Sign in to view your Application Key").ConvertURL("http://www.google.com").Create();
</script>

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

Это самый простой вариант. Дополнительные примеры манипуляции с изображениями, прикрепления снимков экрана к элементам и т. Д. Можно найти в документации .

Джонни
источник
1

$('#cmd2').click(function() {
  	var options = {
		//'width': 800,
  	};
  	var pdf = new jsPDF('p', 'pt', 'a4');
  	pdf.addHTML($("#content2"), -1, 220, options, function() {
    	pdf.save('admit_card.pdf');
  	});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>

<div id="content2" style="background: #fff;border-bottom: 1px solid #ffffff;">
                    	<div class="tokenDet" style="padding: 15px;border: 1px solid #000;width: 80%;margin: 0 auto;position: relative;overflow: hidden;">
                        	<div class="title" style="text-align: center;border-bottom: 1px solid #000;margin-bottom: 15px;">
                            	<h2>Entrance Exam Hall Ticket</h2>
                            </div>
                            <div class="parentdiv" style="display: inline-block;width: 100%;position: relative;">
                            	<div class="innerdiv" style="width: 80%;float: left;">
                            		<div class="restDet">
                                        <div class="div">
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Name</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>Santanu Patra</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>D.O.B.</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>17th April, 1995</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Address</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>P.S. Srijan Corporate Park, Saltlake, Sector 5, Kolkata-91</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Contact Number</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>9874563210</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Email Id</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>santanu@macallied.com</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Parent(s) Name</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>S. Patra</span><br /><span>7896541230</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Exam Center</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>Institute of Engineering & Management</span>
                                            </div>
                                            <div class="label" style="width: 30%;float: left;">
                                                <strong>Hall Number</strong>
                                            </div>
                                            <div class="data" style="width: 70%;display: inline-block;">
                                                <span>COM-32</span>
                                            </div>
                                        </div>
                                    </div>
                            	</div>
                                <div class="sideDiv" style="width: 20%;float: left;">
                                	<div class="atts" style="float: left;width: 100%;">
                                    	<div class="photo" style="width: 115px;height: 150px;float: right;">
                                        	<img src="images/candidateImg.gif" style="width: 100%;"/>
                                        </div>
                                        <div class="sign" style="position: absolute;bottom: 0;right: 0;border-top: 1px dashed #000;left: 80%;text-align: right;">
                                        	<small>Self Attested</small>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <button class="btn btn-info" id="cmd2">Download Token</button>

Сантану
источник
Приведенный выше код не работает ни в одном из протестированных мной браузеров. Когда вы нажимаете кнопку «Загрузить токен», ничего не происходит и никаких ошибок не регистрируется. Не могли бы вы проверить.
Almeister9
0

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

Если у вас есть доступ к файловой системе, то сохранение в формате HTML не так уж сложно (см. Объект файла в документации JS), но PDF не так просто. PDF - это довольно продвинутый файловый формат, который действительно плохо подходит для Javascript. Это требует, чтобы вы записывали информацию в типах данных, которые напрямую не поддерживаются Javascript, например в словах и четырехугольниках. Вам также необходимо предварительно определить систему поиска по словарю, которая должна быть сохранена в файле. Я уверен, что кто-то сможет заставить его работать, но затраченные усилия и время лучше потратить на изучение C ++ или Delphi.

Однако экспорт HTML должен быть возможен, если пользователь предоставляет вам неограниченный доступ.

Джон Леннарт Осенден
источник
2
Почему C ++ и Delphi по наследству лучше создают средство записи PDF?
Raynos 01
2
Потому что эти языки были созданы для создания продвинутого программного обеспечения. Javascript не было. Javascript так и не был завершен, поэтому система прототипов зависла. Автор планировал добавить к нему HL с реальными классами и большим количеством типов данных, но у него не было времени. Так что он был опубликован «как есть». Он не поддерживает указатели, выделение необработанной памяти болезненно, он не поддерживает некоторые из собственных типов данных, которые вы найдете в других языках, он не поддерживает упакованные структуры (структура на C, запись на Pascal) ... список бесконечен. Я люблю JS, но это браузерная игрушка, а не настоящий язык.
Джон Леннарт Осенден
Есть некоторые писатели на основе Java, и если вы посмотрите на размер исходного кода, должно быть достаточно очевидно, что он был бы даже длиннее под Javascript, но ключевой момент заключается в том, что форматирование ввода-вывода и таблицы поиска . Я уверен, что кто-то сможет это сделать, но это будет очень медленно и, по сути, пустая трата времени. А как вы будете вставлять данные о шрифтах? Вы даже не можете получить файл из ОС, не говоря уже о том, чтобы преобразовать его (что представляет собой целую библиотеку) и встроить его. Зачем строить дом из спичек, если можно просто построить нормальный дом?
Джон Леннарт Осенден
2
«но это браузерная игрушка, а не настоящий язык». Это как сказать, что Scheme - не настоящий язык. "должно быть достаточно очевидно, что это будет еще дольше под Javascrip", нет. Java намного более подробный, чем JavaScript. Он должен быть примерно на 2/3 короче версии Java. «но это было бы очень медленно и в основном». Под «чрезвычайно медленным» вы подразумеваете в 3/4 раза медленнее, чем C ++? Не могли бы мы перестать относиться к js как к гражданину второго сорта? Благодарю.
Raynos
11
Независимо от вашего личного мнения, Джон, не могли бы вы перестать утверждать, что «Javascript - не настоящий язык», потому что это чушь. Javascript - чрезвычайно мощный язык, оптимизированный для других целей, чем компилируемый язык низкого уровня, такой как C или C ++. Есть вещи, которые вы можете делать в JS, чего нельзя делать в C или C ++, но означает ли это, что C и C ++ не являются «настоящими» языками? Нет, просто они предназначены для разных вещей. JS - такой же реальный язык программирования, как и любой другой полный по Тьюрингу язык.
Изохронный