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リンクはコンテナの相互接続を実現します

推薦する

ウェブページ上の小さなスペースに大きな画像を配置する方法

出典: www.bamagazine.comウェブページのバナー、ニュースの見出しの周りのスペース、...

ApplicationHost.config (IIS ストレージ構成領域ファイル) の概要

新しく作成された Web サイトの場合は、ASP.NET MVC5 を例に挙げます。セッションを処理...

MySQLでトリガーを作成する方法

この記事の例では、参考のためにMySQLトリガーを作成するための具体的なコードを共有しています。具体...

Windows7 での Mysql5.7 my.ini ファイルの読み込みパスとデータの場所の変更方法

更新: MySQL の公式 Web サイトにアクセスして MySQL インストーラーをインストールし...

HTML の基本 - CSS スタイルシート、スタイル属性、フォーマット、レイアウトの詳細

1.位置:固定一部の Web サイトの右下隅にあるポップアップ ウィンドウなどの、ブラウザーを基準と...

CSS 兄弟要素フローティング分析の概要

float:左/右/なし; 1. 同じレベルフローティング(1)ブロックレベル要素を同じ行に表示する...

Dockerディスク容量不足の問題を解決する

Docker が配置されているサーバーをしばらく稼働させたところ、サーバーのディスク ディレクトリの...

CSS で美しい時計アニメーション効果を実装するためのサンプルコード

仕事を探しています!!!事前準備:まず、このアニメーションは、以前のローディングアニメーションとクー...

Dockerプライベートライブラリの実装

プライベート Docker レジストリのインストールとデプロイは、Docker テクノロジーを導入、...

HTML、CSS、JSコメントの標準的な使用法の概要

必要なコメントを追加することは、責任感と道徳心のあるフロントエンド開発者が持つべき良い習慣であり、コ...

MySQL レプリケーション テーブルの詳細とサンプル コード

MySQL レプリケーション テーブルの詳細な説明テーブル構造、インデックス、デフォルト値などを含む...

MySQLトリガーの詳細な説明と簡単な例

MySQLトリガーの簡単な例文法CREATE TRIGGER <トリガー名> -- トリ...

Tomcat 初回展開 Web プロジェクト プロセス図

独自のWebプロジェクトをtomcatディレクトリの下のwebappsディレクトリに配置します。 R...

MySQLのデッドロックとログに関する詳細な説明

最近、MySQL オンラインでいくつかのデータ異常が発生しましたが、すべて早朝に発生しました。ビジネ...

CSS ペイント API: CSS のような描画ボード

1. Canvas画像をCSS背景画像として使用するCSS ペイント API は、Canvas キャ...