HTML to PDFのピュアクライアントサイドおよびピュアサーバーサイドの実装プログラム
必要条件
ユーザーがフォームに入力し、保存をクリックすると、PDFを直接ダウンロードすることができます。
ソリューションのアイデア
サーバーサイドの生成
アイデア
Google Chromeは17年にChrome Headless機能を独自に開発し、それと並行してpuppeteerを発売したが、これはインターフェースレスだがサーバー機能的な機能ができるブラウザと考えることができる。
そこで、サーバー側でpuppeteerブラウザーを起動し、対象のURLを開き、クローム独自の変換機能を使ってhtmlをpdfに変換することができる。
サーバーサイドでのコアコードの生成
最初にpuppeteerをインストールします。npmのインストールがエラーになる場合があります。
タイプ
cnpm i puppeteer -S
依存関係をインストールします。
jsファイルを作成します。puppeteerブラウザでURLを開き、pdfを保存するだけです。
// html2pdf.js
const puppeteer = require('puppeteer');
(async function(){
// Start the service
const browser = await puppeteer.launch();
// open the tabs
const page = await browser.newPage();
// Go to this address
await page.goto('https://koa.bootcss.com/#context');
// html page to pdf and save to path
await page.pdf({path:"test.pdf",format:'A4'})
// close the browser
await browser.close();
})();
そして、コンソールは次のように入力します。
node html2pdf.js
を実行して、サービスを開始します。
もちろん、ビジネスロジックによっては、module.export でモジュールのメソッドをエクスポートすることも可能です。
デメリット
フォームダイナミックデータを保存できない
ページはサーバーからリクエストされるので、ユーザー入力がリクエストアドレスに保存されていない場合、切り捨てられたpdfがページが埋まっていない初期状態となる。
つまり、彼は静的なページ変換しかできない、我々の要件はユーザー入力が多いのでパス。
クライアントサイドでのコアコードの生成
考えること
- html2canvasを使用し、変換するdomノードを入力し、それを繰り返しながらcanvasに変換します。
- canvasをbase64画像に変換し、jsPDFでpdfファイルを作成し、pdfに画像を挿入します。
不備な点
歪みがある。
ページのスクリーンショットを撮ってpdfに挿入するのと同じなので、ページの解像度や構成が出力画像の品質に影響しそうなことがよくわかりますね。
また、スクリーンショットであるため、ページリンクなどの機能が失われる可能性があります。
テキストの切り捨て
キャンバスがpdfの1ページより大きい場合、出力がおかしくなるので、キャンバスがA4サイズより大きいかどうか判断し、大きい場合は分割して別のページに挿入する必要があります。
ここでまた問題が発生します。分割しているため、キャンバス内のアイテムの構造を解析できず、画像やテキストが途中から切り捨てられる可能性が高いのです。
コアとなるコード
私たちの要件には画像やリンクがないので、歪みの問題はあまり影響しません。また、私たちのフォームは同じ長さの複数の項目が繰り返し構成されており、それらはすべて非常に短く、A4用紙を超えることはありません(これは厳密ではありませんが、必要に応じてDOM要素の幅と高さを取得してDOM要素の高さに準じてトリミングすることが可能です)。
そこで、キャンバスをアイテムに基づいてスライスし、各アイテムにA4用紙1ページを与えて保管するだけにすることにします。
始める前に理解しておきたい、いくつかのコア・メソッド。
html2canvas
// DOM is the DOM node to transform
html2canvas(DOM,{
backgroundColor:"#ffffff",
width:width,
height:height,
scale:2,
allowTaint:true,
}).then((canvas)=>{
// canvas is the canvas after a successful conversion
})
jsPDF
// Create an instance
let pdf = new jsPDF('','pt','a4');
// add the image to the pdf file
// the first parameter is the file to be inserted (base64) format, the second is the file format
// the third fourth is the coordinates of the upper left corner of the picture, the last two are the width and height of the picture after insertion
pdf.addImage(image,'JPEG',10,10,height,width);
// add a new page
pdf.addPage()
// save pdf file
pdf.save()
キャンバス
// canvas is the image to be cropped
// sx, sy are the coordinates to start cropping
// swidth, sHeight is the width and height of the crop
// dx, dy are the coordinates where the cropped image is inserted in the canvas
// sWidth,sHeight is the width and height of the cropped image in the canvas
cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);
/**
* @description: form to pdf file
* @return: pdf
*/
onSubmit(){
// This is the form I want to convert, which has many of the same forms
let form = this.$refs.form;
// Get the width and height of the element
let width = form.getBoundingClientRect().width;
let height = form.getBoundingClientRect().height;
html2canvas(form,{
backgroundColor:"#ffffff",
width:width,
height:height,
scale:2,
allowTaint:true,
}).then((canvas)=>{
let pdf = new jsPDF('','pt','a4');
// for image cutting
let canvasList = this.splitCanvas(canvas, this.forms.length);
// iterate through the canvas list, adding one image per page
canvasList.forEach((item,index)=>{
// convert the image format to base64
let itemImage = item.toDataURL('image/jpeg',1.0);
// leave 10px margins, A4 paper width in 72 resolution monitor is 595px
pdf.addImage(itemImage,'JPEG',10,10,575.28,575.28/item.width*item.height);
// If not the last page, then paginate
index == this.forms.length-1 ? '' : pdf.addPage();
})
// file save
let blob = pdf.output('blob');
pdf.save('test.pdf');
})
},
/**
* @description: cut on canvas
* @param {number} num number of slices
* @param {canvas} canvas
* @return {array} canvas list
*/
splitCanvas(canvas,num){
let height = canvas.height,width = canvas.width;
let chunkHeight = height/num;// the height of each slice
let chunkList = [];// store the result canvas
for(let i=0; i<height ; i+=chunkHeight){
// initialize the crop rectangle box position
let sx = 0,sy = i,sWidth = width,sHeight = chunkHeight,dx = 0, dy = 0;
// Create a canvas node
let canvasItem = document.createElement("canvas");
// Initialize the canvas size
canvasItem.height = chunkHeight;
canvasItem.width = width;
let cxt = canvasItem.getContext("2d");
// put the cropped image into the new canvas node
cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);
chunkList.push(canvasItem);
}
return chunkList;
},
最終効果
フォームが保存された後のページ
<図
pdfに変換したときの効果
<図
HTMLからPDFへの純粋なクライアントサイドと純粋なサーバーサイドのソリューションに関するこの記事はこれで終わりです、より関連するHTMLからPDFへのコンテンツは、スクリプトハウスの過去の記事を検索するか、次の関連記事を参照してください、私はあなたが将来的にもっとスクリプトハウスをサポートして願っています!。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
HTMLページ適応型テーブル(table)
-
レスポンシブフレームワークの分析、テーブル表ヘッダー自動改行クイックソリューション
-
HTMLの横線マークアップとコードコメントの使い方を簡単にマスターできる
-
色は、htmlでは6ビットのHexコードとrgbまたはキーワードで表現されます。
-
html フォーム属性の readonly と disabled を使用する方法
-
meta name="" content="役割の詳細
-
HTMLのテーブル関連タグ10選
-
HTMLマーキー文字のスニペットスクロール
-
標準的なdl,dt,ddタグを持つテーブルリストを破棄する。
-
HTMLのテーブルレイアウトの実用的な使い方を解説