webentwicklung-frage-antwort-db.com.de

Ändern Sie die Standardkopf-/Fußzeile, wenn Sie mit drucken PDF

Ich versuche, Google Chrome als Ersatz für PhantomJS zu verwenden, um HTML in PDF zu rendern. Bisher hat es gut für mich funktioniert. Das einzige Problem, das ich habe, ist, dass ich keinen Weg gefunden habe, den folgenden PhantomJS-Code zu übersetzen:

page.paperSize = {
  footer: {
    contents: phantom.callback(function(pageNum, numPages) {
      return "Power by MyWebsite. Created on "+formatDate(new Date())+"<span style='float:right'>" + pageNum + " / " + numPages + "</span>";
    })
  }
}

Formatierungsdatum ist die gleiche Funktion wie in Frage So formatieren Sie ein JavaScript-Datum

Ich habe jedoch keinen Weg gefunden, dieses Verhalten in Google Chrome kopflos zu replizieren. Ich verwende Chrome Remote Interface (CDP) von https://github.com/cyrus-and/chrome-remote-interface

Dies ist eine Übersicht über meinen Chrome-Remote-Interface-Code:

return new Promise(async function (resolve, reject) {
    const url = "<MyURL here>";
    const [tab] = await Cdp.List()
    const client = await Cdp({ Host: '127.0.0.1', target: tab });
    await Promise.all([
       Network.enable(),
       Page.enable()
    ]);

    Page.loadEventFired(function () { 
         setTimeout(function () {
             resolve(Page.printToPDF({displayHeaderFooter:true}))); //https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
         }, 3000);
    });
    await Page.navigate({ url }); 
};

Ich bekomme das PDF einfach, kann aber nur die standardmäßigen Kopf- und Fußzeilen von Chrome erhalten. Irgendeine Möglichkeit, sie zu ändern?

Note: Ich erkenne, dass ich JavaScript auf meiner Seite verwenden kann, um Elemente an den unteren Rand jeder Seite anzufügen, aber ich würde es vorziehen, die vom Browser angehängte Fußzeile zu ändern, wenn ich sie gefunden habe Es ist viel zuverlässiger, korrekt platziert zu werden, ohne dass andere Divs auf der Seite merkwürdig erneut fließen. 

13
apokryfos

Dies ist eine Aktualisierung/Antwort auf die Frage. Ab Chromium 64 ist es möglich, die Parameter headerTemplate und footerTemplate zu printToPDF zu verwenden.

chrome remote interface Hier ein Beispielcode, der funktionieren sollte:

return new Promise(async function (resolve, reject) {
    const url = "<MyURL here>";
    const [tab] = await Cdp.List()
    const client = await Cdp({ Host: '127.0.0.1', target: tab });
    await Promise.all([
       Network.enable(),
       Page.enable()
    ]);

    Page.loadEventFired(function () { 
         setTimeout(function () {
    //https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
             resolve(Page.printToPDF({
                  displayHeaderFooter:true,
                  footerTemplate: "<span class='pageNumber'> of <span class='totalPages'>"
             }))); 
         }, 3000);
    });
    await Page.navigate({ url }); 
};
12
apokryfos

Es ist möglich, benutzerdefinierte Kopf- und Fußzeilen mithilfe der Tags <header> und <footer> zu erstellen. Ich verwende dies zum Erzeugen von PDFs mit Chrome Headless. Ich habe es nicht in Firefox, IE usw. getestet ... 

<header>
  Custom Header
  <img src="http://imageurl.com/image.jpg"/>
</header>
<div class="content">Page Content - as long as you want</div>
<footer>
  Footer Content
</footer>

das CSS 

@page {
  margin: 0;
}
@media print {
  footer {
    position: fixed;
    bottom: 0;
  }
  header {
    position: fixed;
    top: 0;
  }
}

Der @page { margin: 0 } entfernt die Standardkopf- und -fußzeile.

Hoffe das hilft. 

11
Darren Hall

Es gibt zwei Lösungen für Ihr Problem

A) Drücken Sie den Chromkopf heraus, ohne einen Rand zu hinterlassen:

 @page { 
     margin: 0;
     size: auto;
 }

oder

 @media print {
   @page { margin: 0; }
   body { margin: 1.6cm; }
 }

B) Ursprünglich eine Firefox-Lösung, die für Chrome eine Welt sein sollte

 <html moznomarginboxes mozdisallowselectionprint>

einige probe:

<!DOCTYPE html>
<html moznomarginboxes mozdisallowselectionprint>
<head>
<title>Print PDF without header</title>
<style>
@media print {
    @page { margin: 0; }
    body { margin: 1.6cm; }
}
</style>
</head>
<body>
<p>Some Text in Paragraph to print!</p>
<a href="javascript:print()">Print</a>
</body>
</html>

8
Mason.Chase

Laut diesem Forum gibt es derzeit keine Möglichkeit, dies in Google Chrome zu tun. Sie können nur die Kopf-/Fußzeile ein- oder ausschalten. Dies wird durch den Kommentar angezeigt:

Derzeit gibt es keine Möglichkeit, die Kopfzeile beim Drucken eines Dokuments zu bearbeiten. Derzeit können Sie nur die Kopf- und Fußzeile ein- oder ausschalten, einschließlich Datum, Name der Webseite, Seiten-URL und Anzahl der Seiten, die das Dokument gedruckt werden soll. Unter Umständen möchten Sie im Chrome Web Store nach praktischen Erweiterungen von Drittanbietern suchen, die Sie in Chrome installieren können und die Ihren Anforderungen in Bezug auf das Drucken entsprechen. - Source

Möglicherweise gibt es Erweiterungen von Drittanbietern, um die gewünschte Funktionalität zu erhalten, oder Sie können, wie von Ihnen vorgeschlagen, die Elemente verwenden, die Sie drucken möchten.

3
Chava G

Wenn Sie dies wirklich auf nicht hackige Weise tun möchten, müssen Sie sich mit dem chrome devtools-Protokoll befassen, da die Befehlszeilenschnittstelle nicht viel unterstützt (alias --print-to-pdf ist alles, was Sie erhalten, keine Druckoptionen).

Das Protokoll ist hier dokumentiert: https://chromedevtools.github.io/devtools-protocol/tot

Client-Bibliotheken sind in vielen Sprachen verfügbar und über Paketmanager verfügbar.

Hier einige Beispiele, die ich zusammengestellt habe, um die Verwendung zu demonstrieren:

Die Page.printToPDF-Protokollmethode unterstützt Argumente zum Übergeben von benutzerdefiniertem Markup für Kopf- und Fußzeile.

Grundsätzlich ist das Protokoll in einem protocol.json definiert, den Client-Bibliotheken verwenden, um Klassen/Methoden für die Verwendung in einer beliebigen Anwendung zu generieren. Diese Methoden kapseln die Kommunikation der unteren Ebene mit dem Protokoll.

Ich musste lediglich ein Client-Bibliothekspaket installieren (über npm oder composer), vergewissern, dass Chrome installiert ist, ein wenig Code schreiben und pdfs ohne Kopf-/Fußzeile generieren! Fantastisch.

2
Stoutie

Für diejenigen von Ihnen, die einfach etwas haben wollen, das sofort funktioniert, möchte ich mein heute veröffentlichtes Skript auf der Grundlage der Antwort von apokryfos weitergeben.

Zunächst müssen Sie die Abhängigkeiten installieren

yarn global add chrome-remote-interface

Als Nächstes müssen Sie ein Headless-Chrom mit aktiviertem Debugging-Port starten

chromium-browser --headless --disable-gpu --run-all-compositor-stages-before-draw --remote-debugging-port=9222

Jetzt müssen Sie mein Skript speichern, d. H. Als print-via-chrome.js:

#!/usr/bin/env node

const homedir = require('os').homedir();
const CDP = require(homedir+'/.config/yarn/global/node_modules/chrome-remote-interface/');
const fs = require('fs');

const port = process.argv[2];
const htmlFilePath = process.argv[3];
const pdfFilePath = process.argv[4];

(async function() {

        const protocol = await CDP({port: port});

        // Extract the DevTools protocol domains we need and enable them.
        // See API docs: https://chromedevtools.github.io/devtools-protocol/
        const {Page} = protocol;
        await Page.enable();

        Page.loadEventFired(function () {
                console.log("Waiting 100ms just to be sure.")
                setTimeout(function () {
                        //https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
                        console.log("Printing...")
                        Page.printToPDF({
                                displayHeaderFooter: true,
                                headerTemplate: '<div></div>',
                                footerTemplate: '<div class="text center"><span class="pageNumber"></span></div>',
                                //footerTemplate: '<div class="text center"><span class="pageNumber"></span> of <span class="totalPages"></span></div>'
                        }).then((base64EncodedPdf) => {
                                fs.writeFileSync(pdfFilePath, Buffer.from(base64EncodedPdf.data, 'base64'), 'utf8');
                                console.log("Done")
                                protocol.close();
                        });
                }, 100);
        });

        Page.navigate({url: 'file://'+htmlFilePath});
})();

Nachdem Sie es mit chmod +x print-via-chrome.js ausführbar gemacht haben, sollten Sie HTML-Dateien wie folgt in PDF-Dateien konvertieren können:

./print-via-chrome.js 9222 my.html my.pdf

Vergessen Sie nicht, das Chrom aufzugeben, nachdem Sie Ihre Transformation beendet haben.

Ich bin mir ziemlich sicher, dass diese Lösung alles andere als perfekt ist, aber zumindest funktioniert sie und da ich viele Fragen zu dieser Funktion sah und einige Stunden meiner eigenen Zeit investieren musste, um sie zum Laufen zu bringen, wollte ich meine Lösung teilen. Einige der Probleme, die ich hatte, bezogen sich auf die Header- und FooterTemplates, da leere Vorlagen die vorhandenen nicht ersetzen (Sie benötigen <div></div>). Die neuen Vorlagen werden zwar anders dokumentiert, erscheinen jedoch nicht in einem sichtbaren Bereich, bis sie mit einem <div class="text center"> umschlossen werden oder etwas ähnliches.

1
JepZ