web-dev-qa-db-ja.com

PDFに印刷するときにデフォルトのヘッダー/フッターを変更します

Google ChromeをPhantomJSの代替として使用して、HTMLをPDFにレンダリングしようとしています。これまでのところ、私にとってはうまく機能しています。私が持っている唯一の問題は、次のPhantomJSコードを翻訳する方法を見つけていないことです。

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>";
    })
  }
}

日付のフォーマットは、質問と同じ機能です JavaScript日付のフォーマット方法

ただし、Google Chromeでこの動作をヘッドレスで再現する方法を見つけていません。 https://github.com/cyrus-and/chrome-remote-interface からChromeリモートインターフェイス(CDP)を使用しています

これは、私のchromeリモートインターフェイスコードの概要です。

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 }); 
};

PDFは問題なく取得できますが、デフォルトのChromeヘッダーとフッターしか取得できません。それらを変更する方法はありますか?

:ページ内でJavaScriptを使用して各ページの下部に要素を追加できることを認識していますが、フッターを変更したいエクスポート/印刷時にブラウザによって追加されます。これは、ページ内の他のdivの奇妙なリフローを引き起こすことなく、正しく配置されることがはるかに信頼できるためです。

19
apokryfos

これは質問の更新/回答です。 Chromium 64以降、headerTemplateおよびfooterTemplateパラメーターをprintToPDFに使用することができます

chrome remote interface を使用すると、動作するはずのサンプルコードがあります。

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 }); 
};
14
apokryfos

<header>および<footer>タグを使用して、カスタムヘッダーとフッターを作成することができます。 ChromeHeadless。Firefoxではテストしていません。IEなど...

<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>

cSS

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

@page { margin: 0 }は、デフォルトのヘッダーとフッターを削除します。

お役に立てれば。

13
Darren Hall

あなたの問題には2つの解決策があります

A)マージンを残さずにchrome-headerを押し出します:

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

または

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

B)元々はChromeの世界であるべきFirefoxソリューション

 <html moznomarginboxes mozdisallowselectionprint>

いくつかのサンプル:

<!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

これをハック以外の方法で本当に実行したい場合は、コマンドラインインターフェイスがあまりサポートしていないため、chrome devtoolsプロトコルに通じる必要があります(別名--print-to-pdfがすべてです。印刷オプションはありません)

プロトコルはここに文書化されています: https://chromedevtools.github.io/devtools-protocol/tot

クライアントライブラリは多くの言語で利用可能で、パッケージマネージャーを介して利用できます。

使用法を示すためにまとめたいくつかの例を次に示します。

Page.printToPDFプロトコルメソッドは、ヘッダーとフッターのカスタムマークアップを渡すための引数をサポートします。

基本的に、プロトコルはprotocol.json。クライアントライブラリが、アプリケーションで使用するクラス/メソッドを生成するために使用します。これらのメソッドは、プロトコルとの低レベルの通信をカプセル化します。

クライアントライブラリパッケージを(npmまたはcomposerを介して)インストールし、chromeがインストールされていることを確認し、小さなコードを記述すれば、ヘッダー/フッターのないPDFを生成できました。素晴らしい。

3
Stoutie

箱から出してすぐに動作するものが必要な場合は、apokryfosの答えに基づいて、今日書いたスクリプトを共有したいと思います。

最初に、依存関係をインストールする必要があります

yarn global add chrome-remote-interface

次に、デバッグポートを有効にしてヘッドレスクロムを起動する必要があります

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

今、あなたは私のスクリプトを保存する必要があります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});
})();

chmod +x print-via-chrome.jsで実行可能にすると、次のようにhtmlファイルをpdfファイルに変換できるはずです。

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

変換が完了したら、クロムを終了することを忘れないでください。

このソリューションは完璧からはほど遠いものと確信していますが、少なくとも機能し、この機能について多くの質問を見て、それを機能させるために数時間を費やさなければならなかったので、ソリューションを共有したいと思いました。空のテンプレートは既存のテンプレートに置き換わらないように見えるため(<div></div>が必要)、新しいテンプレートは別のドキュメントに記載されているまで、header-およびfooterTemplatesに関連する問題がいくつかあります。 <div class="text center">または同様のものでラップされます。

2
JepZ

このフォーラム によると、現時点ではGoogle Chromeでこれを行う方法はありません。ヘッダー/フッターをオンまたはオフにするだけです。これはコメントによって示されます:

現在、ドキュメントを印刷するときにヘッダーを編集する方法はありません。現在、ヘッダーとフッターのオン/オフを切り替えることができるのは、日付、Webページの名前、ページURL、および印刷するドキュメントのページ数だけです。 Chrome Webストアをチェックして、Chromeにインストールできる便利なサードパーティ製拡張機能があるかどうかを確認してください。印刷- ソース

あなたが探している機能を得るためのサードパーティの拡張機能があるかもしれませんし、あなたが提案するように、あなたは印刷したい要素を追加するためにJavaScriptを使うことができます。

2
Chava G