前端打印生成pdf


 以下打印均為使用a4紙格式生成pdf

1,空白頁

1.1,圖片前空白頁

多張圖片(大於3)連續出現,可能出現連續的圖片被放在一起,置於下一頁,上一頁則會出現空白頁(正常情況應該是上一頁只有一張圖,下一頁頂部是兩張圖;但是,結果上一頁留白,下一頁頂部是三張圖)

解決:

①,img 添加float樣式

1.2,內容的最后位置出現空白頁

解決:

①,調整頁邊距可能會導致出現空白頁情況,故而可調整頁邊距可能解決

1.3,文字內容少或者以文字結尾,則后面出現空白頁

(發現,如果內容部分是以圖片結尾的,則不會出現額外的空白頁現象)

解決:

①,向頁面末尾添加`<img alt="" style="width:0;height:0">`,即使用空圖展位

2,問題:

①,使用float容易出現,多張圖片連續一起 出現在下一頁(但是上一頁還有空間至少可以排放一張圖的),添加flex colomn布局可以解決,但是flex容易出現截斷問題

2.1,圖片截斷

2.1.1,以下布局容易出現截斷情況

①,圖片用flex布局,容易出現截斷情況

②,position絕對定位布局,也容易發生截斷情況

解決:

①,使用float布局

②,使用table-row布局

③,使用下列圖片樣式

    img {
      display: inline-block;
      page-break-inside: avoid;
      max-width: 100%;
    }

 

3,基於puppeteer.js搭建node服務器,生成pdf文件

 需要自己搭建一套nodejs服務,專門用於生成pdf,頁面需要使用html先繪制出來,通過html鏈接,puppeteer講html生成對應pdf

 

// puppeteer 庫會下載自帶chrome,使用自帶chrome啟動並渲染
const puppeteer = require('puppeteer')
const fs = require('fs')
const sleep = async function (timeout) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve()
    }, timeout)
  })
}

const html2pdf = async function (
  reqParams,
  timeout,
  printDelay,
  checkPdfRenderCompleteJs
) {
  try {
    const { url: pageUrl, showMargin } = reqParams
    const token =
      'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDc4NTI4MzgsInVzZXJJZCI6IjEwMDAwMjE4NyJ9.oDZ6x1e5kZnv1TxFf0cuj03a0eToeLKUdeyMSmoIIbc'
    const whiteList = ['api.g2s.cn', 'orgapi.g2s.cn', 'aries-app.g2s.cn']
    const browser = await puppeteer.launch({
      headless: true,
      // slowMo: 350, // slow down by 250ms
      dumpio: true,
      devtools: false,
      timeout: timeout + 5,
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-gpu',
        '--disable-extensions',
        '--mute-audio',
        '–-no-first-run',
        '--ignore-certificate-errors',
      ],
    })

    const page = await browser.newPage()
    await page.setViewport({
      width: 750,
      height: 1000,
    })
    // page.on('console', (m) => {
    //   console.log('頁面內日志***:' + m.text())
    // })
    page.setJavaScriptEnabled(true)
    // await page.setRequestInterception(true)
    // page.setExtraHTTPHeaders({ access_token: token })
    // page.on('request', async function (req) {
    //   if (req.resourceType() === ['xhr']) {
    //     whiteList.forEach((v) => {
    //       if (!req.url().includes(v)) {
    //         req.headers({ access_token: token })
    //       }
    //     })

    //     // console.log('xhr 請求')
    //   }
    //   // console.log('req:', {
    //   //   url: req.url(),
    //   //   resourceType: req.resourceType(),
    //   //   headers: req.headers(),
    //   // })
    //   await req.continue()
    // })
    // page.on('requestfinished', function (req) {
    //   // console.log('requestfinished:', req)
    // })

    const option = {
      // landscape : false,
      printBackground: true,
      format: 'a4',
      scale: 1,
      // paperWidth : '1mm',
      // paperHeight : '1mm',
      // Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
      pageRanges: '',
      title: '',
      // Whether to silently ignore invalid but successfully parsed page ranges, such as '3-2'. Defaults to false.
      ignoreInvalidPageRanges: false,
      // HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them:
      // date: formatted print date
      // title: document title
      // url: document location
      // pageNumber: current page number
      // totalPages: total pages in the document
      // For example, <span class=title></span> would generate span containing the title.
      // Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
      preferCSSPageSize: true,
      // Allowed Values: ReturnAsBase64, ReturnAsStream
      transferMode: 'ReturnAsStream',
    }
    if (showMargin) {
      Object.assign(option, {
        margin: {
          top: '44px',
          bottom: '74px',
          left: '44px',
          right: '44px',
        },
        displayHeaderFooter: true,
        headerTemplate: `<span class=""></span>`,
        footerTemplate: `
        <style>
        section {
          width:100%;
          padding:0 44px;
          font-family: "宋體";
          font-size: 12px;
          color: #333333;
          font-weight: 400;
          text-align: center;
        }
      </style>
      <section>
        第 <span class="pageNumber"></span> 頁 共 <span class="totalPages"></span> 頁
      </section>`,
      })
    }

    // option.path = savePath

    // page.setViewport({
    //   width: 794,
    //   height: 1123
    // })

    // const login = async function (token) {
    //   const windowHandle = await page.evaluateHandle(() => {
    //     console.log('localStorage', localStorage)
    //     localStorage.setItem('shine-admin-web-zhishi-token', token)
    //   })
    //   console.log('windowHandle', windowHandle)
    // }

    const waitPdfRenderComplete = async function (timeout) {
      let time = 0
      return new Promise(function (resolve, reject) {
        const t = setInterval(function () {
          time += 500
          page
            .evaluate(
              checkPdfRenderCompleteJs ||
                'window.document.readyState === "complete"'
            )
            .then(function (isOk) {
              if (isOk) {
                clearInterval(t)
                resolve('html 解析完成-成功')
              }
            })
          if (time > timeout) {
            setTimeout(function () {
              clearInterval(t)
              reject('html 解析完成-失敗 timeout')
            }, 20)
          }
        }, 500)
      })
    }

    // console.log('open url:' + pageUrl)
    // await login(token)
    await page.goto(pageUrl, { waitUntil: 'networkidle2' })
    console.log('wait pdf render ...')
    const val = await waitPdfRenderComplete(timeout)
    console.log('html 解析完成', val)
    console.log('print delay:' + printDelay)
    await sleep(printDelay)
    // console.log('save pdf file:' + savePath)
    const buf = await page.pdf(option)
    await page.close()
    await browser.close()
    return buf
  } catch (error) {
    console.log('生成pdf錯誤:', error)
    // process.exit(1)
    throw error
  }
}

module.exports = html2pdf

4,基於pdfjs 生成pdf文件

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM