HTML zu PDF mit Node.js.


77

Ich möchte eine druckbare pdfVersion meiner Website-Webseiten erstellen . So etwas wie express.render()nur die Seite rendern alspdf

Kennt jemand ein Knotenmodul, das das macht?

Wenn nicht, wie würden Sie vorgehen, um eine zu implementieren? Ich habe einige Methoden gesehen, die über die Verwendung von Headless-Browsern sprechen, bin mir phantom.jsaber nicht sicher, wie der Fluss abläuft.


Ich hoffe, dass dies immer noch relevant ist, aber es gibt jetzt diese Seite simpe.li, die einige vordefinierte Vorlagen enthält, die Sie auswählen und verwenden können. Könnte in einigen Situationen nützlich sein.
David Gatti

Antworten:


87

Erweiterung auf Mustafas Antwort.

A) Installieren Sie http://phantomjs.org/ und dann

B) Installieren Sie das Phantomknotenmodul https://github.com/amir20/phantomjs-node

Geben Sie hier die Bildbeschreibung ein

C) Hier ist ein Beispiel für das Rendern eines PDFs

var phantom = require('phantom');   

phantom.create().then(function(ph) {
    ph.createPage().then(function(page) {
        page.open("http://www.google.com").then(function(status) {
            page.render('google.pdf').then(function() {
                console.log('Page Rendered');
                ph.exit();
            });
        });
    });
});

Ausgabe des PDF:

Geben Sie hier die Bildbeschreibung ein

BEARBEITEN: Stilles Drucken des PDF

java -jar pdfbox-app-2.0.2.jar PrintPDF -silentPrint C:\print_mypdf.pdf


24
Lädt dies auch das CSS? Wenn ich eine Seite rendere, wird Text angezeigt, aber es gibt kein CSS.

3
Eines der Probleme bei dieser Lösung ist, dass Sie keine anklickbaren Links auf der Webseite erhalten. Dies entspricht dem Erstellen eines Screenshots und dem Einbetten des Bilds in PDF. Wenn das für Sie funktioniert, dann ist dies eine großartige Lösung.
Psuhas

Dieses Modul phantomjs-nodeexistiert nicht auf NPM, verwendet npm install phantom@2 -Sfür Knoten v kleiner als 5.0 oder npm install phantom -Sfür Knoten Version 5.0 oder höher
TetraDev

Wenn ich HTML in PDF konvertiere, gibt es 4-5 Seiten in HTML. Ich möchte einen Seitenumbruch zwischen zwei Seiten verwenden. Dies ist mein URL-Link, den ich als PDF konvertieren möchte. " ishtech.xyz//web/#/reports_view?StartDate=11/14/… "
Hardik Mandankaa

3
PhantomJS ist kein aktives Projekt mehr
Scott Stensland

22

Phantom.js ist ein Headless-Webkit-Server, der jede Webseite lädt und im Speicher rendert. Obwohl Sie sie möglicherweise nicht sehen können, gibt es eine Bildschirmaufnahmefunktion, mit der Sie die aktuelle Ansicht als PNG, PDF exportieren können , JPEG und GIF. Schauen Sie sich dieses Beispiel aus der Dokumentation von phantom.j an


17

Wenn Sie HTML in PDF exportieren möchten. Sie haben viele Möglichkeiten. ohne Knoten sogar

Option 1: Haben Sie eine Schaltfläche auf Ihrer HTML-Seite, die die Funktion window.print () aufruft. Verwenden Sie das native HTML des Browsers als PDF. Verwenden Sie Medienabfragen, damit Ihre HTML-Seite im PDF-Format gut aussieht. Außerdem haben Sie den Druck vor und nach Ereignissen, mit denen Sie vor dem Druck Änderungen an Ihrer Seite vornehmen können.

Option 2. htmltocanvas oder rasterizeHTML . Konvertieren Sie Ihr HTML in Zeichenfläche und rufen Sie dann toDataURL () für das Zeichenflächenobjekt auf, um das Bild abzurufen. Verwenden Sie eine JavaScript-Bibliothek wie jsPDF , um dieses Bild einer PDF-Datei hinzuzufügen. Nachteil dieses Ansatzes ist, dass das PDF nicht mehr bearbeitet werden kann. Wenn Sie Daten aus PDF extrahieren möchten, gibt es dafür verschiedene Möglichkeiten.

Option 3. @Jozzhard Antwort


Welche Browser verfügen über eine integrierte Option für HTML zu PDF? Ich kann es derzeit nur in Chrome sehen.
Mwotton

11

Die beste Lösung, die ich gefunden habe, ist HTML-PDF. Es ist einfach und arbeitet mit großem HTML.

https://www.npmjs.com/package/html-pdf

So einfach ist das:

    pdf.create(htm, options).toFile('./pdfname.pdf', function(err, res) {
        if (err) {
          console.log(err);
        }
    });

1
Absolut toll. Es funktioniert auch mit externen URLs, wenn Sie es mit requestify kombinieren.
TetraDev

2
Es berücksichtigt die CSS? die Klassen?
gabrielAnzaldo

1
@ gabodev77, ja das tut es.
Rückruf

sein Support Style Tag oder nicht?
Yash

2
Zu Ihrer Information - dieses Paket wurde seit 2017 nicht mehr aktualisiert und weist eine kritische Sicherheitsanfälligkeit auf. Npmjs.com/advisories/1095 Wahrscheinlich am besten mit einer anderen Option :)
D. Gibbs


5

PDF aus externer URL erstellen

Hier ist eine Anpassung der vorherigen Antworten, die verwendet html-pdf, aber auch kombiniert wird, requestifysodass sie mit einer externen URL funktioniert:

Installieren Sie Ihre Abhängigkeiten

npm i -S html-pdf requestify

Erstellen Sie dann das Skript:

//MakePDF.js

var pdf = require('html-pdf');
var requestify = require('requestify');
var externalURL= 'http://www.google.com';

requestify.get(externalURL).then(function (response) {
   // Get the raw HTML response body
   var html = response.body; 
   var config = {format: 'A4'}; // or format: 'letter' - see https://github.com/marcbachmann/node-html-pdf#options

// Create the PDF
   pdf.create(html, config).toFile('pathtooutput/generated.pdf', function (err, res) {
      if (err) return console.log(err);
      console.log(res); // { filename: '/pathtooutput/generated.pdf' }
   });
});

Dann laufen Sie einfach von der Kommandozeile aus:

node MakePDF.js

Sehen Sie zu, wie Ihre pixelgenaue PDF-Datei für Sie erstellt wird (kostenlos!)


Es gibt ein Problem html-pdf, das manchmal nur zum Erfolg beim
Erstellen

Wie würden Sie die erstellte PDF direkt in den Browser rendern, ohne die Datei zuerst speichern zu müssen?
MartinWebb

Mit einem binären Stream könnte es gemacht werden. Theoretisch wird es nicht gespeichert, sondern direkt an den Browser weitergeleitet. Obwohl ich mit Node arbeitete, konnte ich es nur zum Laufen bringen, indem ich zuerst das temporäre PDF speicherte, dann den Binär-Stream abrief, den Binär-Stream herunterlud und dann das temporäre PDF löschte.
TetraDev

Ich erhalte eine Fehlermeldung von html-pdf - ReferenceError: Variable $ kann nicht gefunden werden. Könnte dies passieren, weil die Seite, die ich lade, Javascript enthält, das ausgeführt werden muss? Irgendwelche Ideen wären hilfreich.
MindWire

@ TetraDev: Ich muss mich einschränken, um 1 Seite PDF zu generieren. Was werden Änderungen sein?
Shiva

5

Paket

Ich habe HTML-PDF verwendet

Einfach zu bedienen und ermöglicht nicht nur das Speichern von PDFs als Datei, sondern auch das Weiterleiten von PDF-Inhalten an einen WriteStream (sodass ich sie direkt an Google Storage streamen kann, um dort meine Berichte zu speichern).

Verwenden von CSS + Bildern

Es berücksichtigt CSS. Das einzige Problem, mit dem ich konfrontiert war - es ignorierte meine Bilder. Die Lösung, die ich gefunden habe, bestand darin, die URL im srcAttributwert durch base64 zu ersetzen , z

<img src="data:image/png;base64,iVBOR...kSuQmCC">

Sie können dies mit Ihrem Code tun oder einen der Online-Konverter verwenden, z. B. https://www.base64-image.de/

Kompilieren Sie gültigen HTML-Code aus HTML-Fragment + CSS

  1. Ich musste ein Fragment von mir bekommen html Dokuments abrufen (ich habe gerade die .html () -Methode auf den jQuery-Selektor angewendet).
  2. Dann habe ich den Inhalt der entsprechenden cssDatei gelesen .

Mit diesen beiden Werten (in Variablen gespeichert htmlund cssentsprechend) habe ich einen gültigen HTML-Code unter Verwendung der Vorlagenzeichenfolge kompiliert

var htmlContent = `
<!DOCTYPE html>
<html>
  <head>
    <style>
      ${css}
    </style>
  </head>
  <body id=direct-sellers-bill>
    ${html}
  </body>
</html>`

und an die createMethode von html-pdf übergeben .


Kann HTML-PDF von ungültigen URLs heruntergeladen werden, z. B. von Seiten der Google Chrome-Erweiterung / gtar.html?
Malcolm Salvador

Wie können Sie erwarten, dass ein System etwas von einer ungültigen URL erhält?
user1990962

4

Für diejenigen, die PhantomJS nicht zusammen mit einer Instanz von Chrome / Firefox auf ihrem Server installieren möchten - oder weil das PhantomJS-Projekt derzeit ausgesetzt ist , gibt es hier eine Alternative.

Sie können die Konvertierungen in APIs auslagern, um die Aufgabe zu erledigen. Viele existieren und variieren, aber Sie erhalten einen zuverlässigen Dienst mit aktuellen Funktionen (ich denke, CSS3, Web-Schriftarten, SVG, Canvas-kompatibel).

Mit PDFShift (Haftungsausschluss, ich bin der Gründer) können Sie dies beispielsweise einfach mithilfe des requestPakets tun :

const request = require('request')
request.post(
    'https://api.pdfshift.io/v2/convert/',
    {
        'auth': {'user': 'your_api_key'},
        'json': {'source': 'https://www.google.com'},
        'encoding': null
    },
    (error, response, body) => {
        if (response === undefined) {
            return reject({'message': 'Invalid response from the server.', 'code': 0, 'response': response})
        }
        if (response.statusCode == 200) {
            // Do what you want with `body`, that contains the binary PDF
            // Like returning it to the client - or saving it as a file locally or on AWS S3
            return True
        }

        // Handle any errors that might have occured
    }
);

1

Meiner Ansicht nach ist dies am besten über eine API möglich, damit Sie Ihrer App keine große und komplexe Abhängigkeit hinzufügen, in der nicht verwalteter Code ausgeführt wird, der häufig aktualisiert werden muss.

Hier ist eine einfache Möglichkeit, die für 800 Anfragen / Monat kostenlos ist:

var CloudmersiveConvertApiClient = require('cloudmersive-convert-api-client');
var defaultClient = CloudmersiveConvertApiClient.ApiClient.instance;

// Configure API key authorization: Apikey
var Apikey = defaultClient.authentications['Apikey'];
Apikey.apiKey = 'YOUR API KEY';



var apiInstance = new CloudmersiveConvertApiClient.ConvertWebApi();

var input = new CloudmersiveConvertApiClient.HtmlToPdfRequest(); // HtmlToPdfRequest | HTML to PDF request parameters
input.Html = "<b>Hello, world!</b>";


var callback = function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ' + data);
  }
};
apiInstance.convertWebHtmlToPdf(input, callback);

Mit dem oben beschriebenen Ansatz können Sie die API auch lokal oder in Ihrer eigenen Infrastruktur installieren, wenn Sie dies bevorzugen.


0

Verwenden Sie HTML-PDF

var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
var options = { format: 'Letter' };

pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/app/businesscard.pdf' } 
});

0

Für den Fall, dass Sie hier ankommen und nach einer Möglichkeit suchen, PDF aus Ansichtsvorlagen in Express zu erstellen, haben ein Kollege und ich Express-Template-to-PDF erstellt

Damit können Sie PDF-Dateien aus beliebigen Vorlagen generieren, die Sie in Express verwenden - Pug, Nunjucks, was auch immer.

Es hängt von HTML-PDF ab und ist so geschrieben, dass es in Ihren Routen verwendet wird, genau wie Sie res.render verwenden:

const pdfRenderer = require('@ministryofjustice/express-template-to-pdf')

app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')

app.use(pdfRenderer())

Wenn Sie res.render verwendet haben, sollte die Verwendung offensichtlich aussehen:

app.use('/pdf', (req, res) => {
    res.renderPDF('helloWorld', { message: 'Hello World!' });
})

Sie können Optionen an html-pdf übergeben, um die Seitengröße des PDF-Dokuments usw. Zu steuern

Nur auf der hervorragenden Arbeit anderer aufbauen.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.