Grundlegendes zu Google Chrome Konvertieren von HTML in PDF-Funktionen


Kürzlich habe ich in einem Startup das Problem des Generierens von Tickets im PDF-Format gelöst. Zu diesem Zeitpunkt war bereits eine Website mit einem etablierten Stapel von Technologien fertig, daher suchte ich nach einem Ansatz, für den keine zusätzlichen Tools erforderlich sind. Am Ende schlug ich vor, zuerst Tickets im HTML-Format zu erstellen und dann mit dem Chrome-Browser in PDF zu konvertieren. Wie sich herausstellte, kann diese Methode nicht nur Tickets generieren, die reich mit CSS dekoriert sind, sondern auch eine Vielzahl von Berichten mit Diagrammen in JavaScript. In diesem Artikel werde ich erläutern, wie Sie Chrome für diese Zwecke starten, einige Tipps zum Anpassen von CSS geben und die Nachteile dieser Lösung erläutern.


Alternative Optionen werden hier nicht behandelt, da bereits genug darüber geschrieben wurde, sie leicht zu finden sind und es sich um vorgefertigte Tools handelt, deren Informationen in den Primärquellen besser zu finden sind - in der Dokumentation auf offiziellen Websites. Die vorgeschlagene Methode ist kein eigenständiges Werkzeug und eher ein Nebenprodukt der Entwicklung mehrerer Technologien. Im russischsprachigen Segment des Internets werden nur wenige Informationen gesammelt, daher habe ich beschlossen, die Lücke zu schließen.


Warum wird diese Option gewählt?


Der größte Vorteil ist, dass Chrome den Technologie-Stack nicht erweitern muss, um PDFs zu generieren. Frontend-Entwickler erstellen HTML mit vertrauten Entwicklungstools und sehen sofort die Zwischenergebnisse der Arbeit im Browser. Gleichzeitig dreht sich Chrome wahrscheinlich in Tests und die Übertragung auf das Backend ist nicht schwierig. Es sollte auch beachtet werden, dass der Codierer auf das gesamte Arsenal an CSS-Eigenschaften einschließlich Flexbox und Grid zugreifen kann.
Ich werde im Verlauf des Artikels über die Mängel und Möglichkeiten sprechen, sie zu umgehen.


Wir lösen das Problem in einer Zeile


In der Befehlszeile rufen wir Chrome im Headless-Modus auf und speichern die Seite im PDF-Format:


chrome --headless --disable-gpu --print-to-pdf https://google.com 

Linux-Benutzer müssen möglicherweise einen chromium-browser anstelle von chrome ausführen.
MAC-Benutzer finden es möglicherweise hilfreich, Alias ​​vorab zu erstellen:


 alias chrome="/Applications/Google\\ \\Chrome.app/Contents/MacOS/Google\\ \\Chrome" 

UPDATE: In den Kommentaren wurde klargestellt, dass Windows-Benutzer den Namen der PDF-Datei explizit festlegen müssen --print-to-pdf=output.pdf


Wenn Sie bereits über einen HTML-Dokumentgenerator verfügen, geben Sie anstelle von https://google.com die URL an, unter der dieses Dokument empfangen werden soll.


Öffnen Sie die Datei output.pdf im lokalen Verzeichnis und sehen Sie sich das Ergebnis an.
Das erste, was auffällt, ist das Vorhandensein einer Kopfzeile mit einem Druckdatum und einer Fußzeile mit einer URL und einer Paginierung. Um sie zu entfernen, müssen Sie einige CSS-Regeln hinzufügen. Es ist unwahrscheinlich, dass diese Regeln zu google.com hinzugefügt werden. Für weitere Arbeiten ist es daher besser, ein eigenes HTML-Dokument zu erstellen.


CSS hinzufügen


CSS hat eine spezielle Medienabfrage @page , die zum Drucken verwendet wird. Wir werden Einrückungen @page , damit @page und Fußzeile einfach nicht passen:


 @page { size: A4; margin: 0mm; } 

Diese Methode funktioniert nur für einseitige Dokumente. Wenn Sie zwei oder mehr Seiten drucken, bleibt die Fußzeile mit der URL und der Seitennummerierung unten unten. Sie können Chrome explizit displayHeaderFooter = False , die Anzeige von Kopf- und Fußzeile zu displayHeaderFooter = False , indem Sie den displayHeaderFooter = False wird er jedoch nicht in die Befehlszeilenschnittstelle verschoben. Um dorthin zu gelangen, benötigen Sie Tools, um die Arbeit mit dem Browser zu automatisieren: Selen oder Puppenspieler. Als nächstes werde ich die erste Option in Betracht ziehen, da mein Projekt Python verwendet hat.


Starten Sie Chrome über Selen


Installieren Sie Selenium mit dem Befehl pip install selenium , laden Sie den Chrome-Treiber herunter, der Ihrer Chrome-Version entspricht, von http://chromedriver.chromium.org/ und verwenden Sie die Funktion get_pdf_from_html aus dem folgenden Beispiel:


 import sys from selenium import webdriver from selenium.webdriver.chrome.options import Options import json, base64 def get_pdf_from_html(path, chromedriver='./chromedriver', print_options = {}): #  Chrome webdriver_options = Options() webdriver_options.add_argument('--headless') webdriver_options.add_argument('--disable-gpu') driver = webdriver.Chrome(chromedriver, options=webdriver_options) #   url driver.get(path) #    calculated_print_options = { 'landscape': False, 'displayHeaderFooter': False, 'printBackground': True, 'preferCSSPageSize': True, } calculated_print_options.update(print_options) #    pdf  result = send_devtools(driver, "Page.printToPDF", calculated_print_options) driver.quit() #    base64 -  return base64.b64decode(result['data']) def send_devtools(driver, cmd, params={}): resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id url = driver.command_executor._url + resource body = json.dumps({'cmd': cmd, 'params': params}) response = driver.command_executor._request('POST', url, body) if response['status']: raise Exception(response.get('value')) return response.get('value') if __name__ == "__main__": if len(sys.argv) != 3: print ("usage: converter.py <html_page_sourse> <filename_to_save>") exit() result = get_pdf_from_html(sys.argv[1]) with open(sys.argv[2], 'wb') as file: file.write(result) 

Um eine PDF-Datei zu erhalten, können Sie dieses Beispiel über die Befehlszeile ausführen, indem Sie die URL und den Dateinamen get_pdf_from_html , um die PDF-Datei zu speichern, oder die Funktion get_pdf_from_html und drei Argumente übergeben:


  1. Pfad - URL des HTML-Dokuments;
  2. chromedriver - der Pfad auf dem lokalen Computer zum Chrome-Treiber (standardmäßig muss er sich im lokalen Verzeichnis befinden);
  3. print_options - zusätzliche Druckattribute.

Es ist zu beachten, dass Selenium keine Standardschnittstelle zum Drucken einer Seite in PDF hat und nur Chrome dies kann. Sie müssen daher direkt driver.command_executor._request .


Lassen Sie uns nun sehen, welche Tools verfügbar sind, um die Platzierung von Inhalten in mehrseitigen Dokumenten zu steuern.


CSS-Typografie


Beim Duplexdruck können Sie für die rechte und die linke Seite einzeln unterschiedliche Ränder vom Rand festlegen, wenn Sie sie in Zukunft zusammenfügen möchten:


 @page :left { margin-left: 4cm; margin-right: 2cm; } @page :right { margin-left: 4cm; margin-right: 2cm; } 

Für die erste Seite können Sie Ihr eigenes Design angeben, z. B. einen vergrößerten Einzug vom oberen Rand:


 @page :first { margin-top: 10cm /* Top margin on first page 10cm */ } 

Es ist möglich, den Seitenumbruch vor der Überschrift der ersten Ebene so festzulegen, dass er auf einer ungeraden Seite beginnt:


 h1 { page-break-before : right } 

Mit der Eigenschaft " page-break-after können Sie einen Seitenumbruch unmittelbar nach einem Element verhindern, z. B. nach einem Header der zweiten Ebene:


 h2 { page-break-after : avoid } 

Die Eigenschaft zum page-break-inside hilft dabei, Seitenumbrüche zu vermeiden, wenn dies unerwünscht ist, z. B. in der Mitte einer Tabelle


 table { page-break-inside : avoid } 

Die orphans orphans und " orphans verhindern Seitenumbrüche am Anfang und Ende eines Absatzes:


 @page { orphans:4; widows:2; } 

Was ist mit Leistung?


Auf einem Core i5-8600K 3600MHz in einen Stream dauert eine einfache Dokumentkonvertierung 0,6 Sekunden. Auf meiner tragbaren Schreibmaschine Ende 2013 2,4 GHz - 1,5 Sekunden.
Offensichtlich werden die Hauptressourcen für das Starten des Browsers ausgegeben. Sie können die Konvertierungszeit für eine große Anzahl von Dateien verkürzen, wenn Sie Chrome einmal als Microservice ausführen und ihm eine URL zur Konvertierung senden. Die Implementierung dieser Methode würde den Rahmen dieses Artikels sprengen.


Was ist sonst noch falsch?


Ich sehe zwei Hauptprobleme:


  1. Die Unmöglichkeit, einfach die Position von Elementen in einem Dokument zu bestimmen. Dies macht es schwierig, ein Inhaltsverzeichnis mit automatischer Anzeige der Seitenzahlen zu erstellen, insbesondere wenn die Größe des Inhalts nicht im Voraus bekannt ist.
  2. Die Conversion von Chrome ist das Produkt von Google, das eine Vielzahl von Informationen über Nutzer sammelt. Wenn Datenlecks aus dem Dokument nicht akzeptabel sind, sollten Sie bei der vorgeschlagenen Lösung vorsichtig sein - schließen Sie den Browser mit Zugriff auf externe Ressourcen oder suchen Sie sogar nach einer anderen Lösung. Die Verwendung von Open Source Chromium löst das Problem nicht - es wurden bereits Fehler von Google gefunden.

Schlussfolgerungen


Ich schlage vor, Schlussfolgerungen über die Zulässigkeit der alleinigen Anwendung dieses Ansatzes zu ziehen. Jedes Projekt ist auf seine Weise einzigartig. Ob diese Methode für Ihr Projekt geeignet ist, liegt bei Ihnen.

Source: https://habr.com/ru/post/de459112/


All Articles