HTMLからPDFへの変換のための純粋なクライアント側と純粋なサーバー側の実装ソリューション

HTMLからPDFへの変換のための純粋なクライアント側と純粋なサーバー側の実装ソリューション

必要

ユーザーがフォームに入力して「保存」をクリックすると、PDF ドキュメントを直接ダウンロードできます。

解決

サーバー世代

アイデア

Google Chromeは2017年にChrome Headless機能を独自開発し、同時にPuppeteerをリリースしました。インターフェースがないブラウザでありながら、サーバー機能を完備していると言えます。

したがって、サーバー上で Puppeteer ブラウザを起動し、ターゲット URL を開き、Chrome ブラウザの組み込み変換機能を使用して HTML を PDF に変換できます。

サーバーがコアコードを生成する

まず、puppeteer をインストールする必要があります。NPM のインストールは失敗する可能性があります。cnpm Taobao ミラーを使用してインストールするのが最適です。

依存関係をインストールするには、 cnpm i puppeteer -Sと入力します。

js ファイルを作成し、Puppeteer ブラウザで URL を開いて PDF を保存します。

// html2pdf.js

'puppeteer' という定数が必要です。
(非同期関数(){
    // サービスを開始します const browser = await puppeteer.launch();
    // タブを開く const page = await browser.newPage();
    // このアドレスに移動します await page.goto('https://koa.bootcss.com/#context');
    // HTML ページを PDF に変換し、パスに保存します
    page.pdf({path:"test.pdf",format:'A4'}) を待ちます
    // ブラウザを閉じる await browser.close();
})();

次に、コンソールにnode html2pdf.jsと入力してサービスを開始します。

もちろん、ビジネス ロジックに応じて module.export を使用してモジュール メソッドをエクスポートすることもできます。

欠点

動的フォームデータを保存できません

ページはサーバーから要求されるため、ユーザー入力が要求アドレスに保存されていない場合、傍受された PDF は入力されていないページの初期状態になります。

つまり、静的なページしか変換できませんが、私たちの要件では大量のユーザー入力が必要なので、合格です。

クライアントがコアコードを生成する

アイデア

  • html2canvasを使用して、変換する必要があるDOMノードを入力し、それをトラバースしてキャンバスに変換します。
  • キャンバスを base64 イメージに変換し、jsPDF を使用して PDF ファイルを作成し、そのイメージを PDF に挿入します。

欠点

ねじれ。

ページのスクリーンショットを撮って、それを PDF に挿入するのと似ているため、ページの解像度と構成が出力画像の品質に影響を与える可能性が高いことがわかります。

同時に、スクリーンショットであるため、ページリンクなどの機能が失われる可能性があります。

テキストの切り捨て

キャンバスが PDF ページのサイズより大きい場合、出力は正しくありません。このとき、キャンバスが A4 サイズを超えているかどうかを判断する必要があります。超えている場合は、キャンバスを分割して別のページに挿入します。

ここで再び問題が発生します。画像がセグメント化されているため、キャンバス内のアイテムの構造を分析できず、画像またはテキストが半分に切り取られる可能性が非常に高くなります。

コアコード

私たちのニーズには画像やリンクは含まれていないため、歪みの問題はほとんど影響しません。同時に、私たちのフォームは同じ長さの複数の繰り返し項目で構成されており、これらの項目は非常に短く、A4 用紙を超えることはありません (これは厳密ではありませんが、必要に応じて、DOM 要素の幅と高さを取得し、DOM 要素の高さに応じて切り抜くことができます)。

そこで、アイテムごとにキャンバスを直接分割し、各アイテムを A4 用紙 1 ページに保存する予定です。

始める前に理解しておく必要があるコアメソッドがいくつかあります。

html2キャンバス

   // DOMは変換されるDOMノードです html2canvas(DOM,{
        背景色:"#ffffff",
        幅:幅、
        高さ:高さ、
        スケール:2,
        汚染を許可する:true、
    }).then((キャンバス)=>{
        // キャンバスは変換が成功した後のキャンバスです})

jsPDF

   // インスタンスを作成します。let pdf = new jsPDF('','pt','a4');
    // 画像を PDF ファイルに追加します // 最初のパラメーターは挿入するファイル形式 (base64)、2 番目はファイル形式です // 3 番目と 4 番目は画像の左上隅の座標、最後の 2 つは挿入後の画像の幅と高さです pdf.addImage(image,'JPEG',10,10,height,width);
    // 新しいページを追加する pdf.addPage()
    // PDFファイルを保存する pdf.save()

キャンバス

  // canvas は切り取る画像です // sx、sy は切り取りを開始する座標です // swidth、sHeight は切り取りの幅と高さです // dx、dy は切り取った画像を canvas に挿入する座標です // sWidth、sHeight は切り取った画像の canvas 内での幅と高さです cxt.drawImage(canvas, sx, sy, sWidth, sHeight, dx, dy, sWidth, sHeight);
/**
 * @description: フォームを PDF ファイルに変換します* @return: pdf
 */
送信(){
    // これは変換したいフォームです。このフォームには同一のフォームが多数あります。let form = this.$refs.form;
    // 要素の幅と高さを取得します。let width = form.getBoundingClientRect().width;
    高さを form.getBoundingClientRect().height に設定します。
    html2canvas(フォーム,{
        背景色:"#ffffff",
        幅:幅、
        高さ:高さ、
        スケール:2,
        汚染を許可する:true、
    }).then((キャンバス)=>{
        pdf = new jsPDF('','pt','a4');
        // 画像を切り取ります let canvasList = this.splitCanvas(canvas,this.forms.length);

        // キャンバスリストを走査し、各ページに画像を追加します canvasList.forEach((item,index)=>{
            // 画像フォーマットをbase64に変換する
            itemImage を item.toDataURL('image/jpeg',1.0); とします。
            // 10px の余白を確保します。A4 用紙の幅は 72 解像度のモニターでは 595px です。
            pdf.addImage(itemImage,'JPEG',10,10,575.28,575.28/item.width*item.height);
            // 最後のページでない場合は、ページ区切り index == this.forms.length-1 ? '' : pdf.addPage();
        })
        // ファイルを保存します。let blob = pdf.output('blob');
        
        pdf.save('test.pdf');
    })
},
/**
 * @description: キャンバスをカット * @param {number} num スライスの数 * @param {canvas} キャンバス 
 * @return {array} キャンバスリスト*/
splitCanvas(キャンバス,数値){
    高さを canvas.height、幅を canvas.width とします。
    let chunkHeight = height/num; // 各スライスの高さ let chunkList = []; // 結果のキャンバスを保存
    for(let i=0; i<height; i+=chunkHeight){
        // 切り抜き四角形の位置を初期化します。let sx = 0,sy = i,sWidth = width,sHeight = chunkHeight,dx = 0, dy = 0;
        // キャンバス ノードを作成します。let canvasItem = document.createElement("canvas");
        // キャンバス サイズを初期化します。canvasItem.height = chunkHeight;
        キャンバスアイテムの幅 = 幅;
        cxt = canvasItem.getContext("2d"); とします。
        // 切り取った画像を新しいキャンバス ノードに配置します。cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);
        chunkList.push(キャンバスアイテム); 
    }
    chunkList を返します。
},

最終結果

フォームを保存した後のページ

PDFへの変換の効果

これで、HTML から PDF への純粋なクライアント側および純粋なサーバー側の実装ソリューションに関するこの記事は終了です。HTML から PDF への関連コンテンツの詳細については、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

<<:  MySQL に外部キー制約を追加する具体的な方法

>>:  Dockerリンクはコンテナの相互接続を実現します

推薦する

Centos8で静的IPを設定する方法の詳細な説明

CentOS 8をインストールした後、ネットワークを再起動すると次のエラーが表示されますエラーメッセ...

Vueデータ監視の原理の詳細な説明

目次1. はじめにII. 監視対象2.1 なぜオブジェクトを監視する必要があるのですか? 2.2 デ...

MySQL のテーブルリターンとインデックスカバレッジの例の詳細な説明

目次インデックスタイプインデックス構造非クラスター化インデックスクエリインデックスカバー要約するイン...

js 配列エントリ() 反復メソッドを取得する

目次1.entires() メソッドの詳細な構文2.entires() メソッドの一般的な使用法と注...

クラウドサーバーパゴダパネルの詳細なインストール手順

目次0x01. パゴダパネルをインストールする0x02. サーバーポートを開く0x03. ブラウザを...

Linux デバイス用ネットワーク ドライバーの紹介

有線ネットワーク: イーサネット 無線ネットワーク: 4G、WiFi、Bluetooth、5G 概要...

DockerのIDEA構成プロセス

IDEA は Java で最も一般的に使用されている開発ツールであり、Docker は最も人気のある...

単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

目次プロジェクトの背景改善案データ特性を観察するマルチプロセスアイデアの要約データ処理スキルプロジェ...

デザイナーが再びハマーの公式サイトに不満を述べる

昨年、この公開書簡は大ヒットし、羅永浩氏を驚かせた。今日、著者が新しい章を発表するとは思ってもみなか...

Ubuntu 20.04 LTS で Java 開発環境を構成する

Java開発キットjdkをダウンロードするJDK のダウンロード アドレスはhttp://www.o...

Windows での MySQL スケジュールバックアップ スクリプトの実装

Windows サーバーでデータベース データを定期的にバックアップする場合は、Windows タス...

CentOS 8 カスタム ディレクトリ インストール nginx (チュートリアルの詳細)

1. ツールとライブラリをインストールする# PCRE は、Perl 互換の正規表現ライブラリを含...

React イベントバインディングの詳細

目次クラスコンポーネントイベントバインディング関数コンポーネントイベントバインディング要約するRea...

MySQL ストアド プロシージャのエラー処理例の詳細な説明

この記事では、例を使用して MySQL ストアド プロシージャのエラー処理について説明します。ご参考...