欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

純前端生成PDF(jsPDF)并下載保存或上傳到OSS的代碼示例

 更新時(shí)間:2025年01月10日 10:44:37   作者:寶子向前沖  
這篇文章主要介紹了純前端生成PDF(jsPDF)并下載保存或上傳到OSS的相關(guān)資料,主要步驟包括獲取DOM節(jié)點(diǎn)、生成PDF、保存或上傳PDF,文章還提到了一些注意事項(xiàng),需要的朋友可以參考下

前言

在工作中遇到了一個(gè)需求,就是把前端頁面生成PDF并保存在本地,因?yàn)榍岸司W(wǎng)站可能會(huì)展示各種表格,圖表信息內(nèi)容并帶有比較鮮艷的色彩樣式,如果讓后端生產(chǎn)的PDF的話樣式可能和前端頁面展示的有所差異,所以這個(gè)任務(wù)就落到了前端的身上。

技術(shù)涉及

  • jsPDF
  • html2canvas 

  • ali-oss

代碼實(shí)現(xiàn)

1、獲取DOM結(jié)點(diǎn)

首先需要獲取需要打印的DOM結(jié)點(diǎn),這個(gè)時(shí)候獲取的DOM結(jié)點(diǎn)是帶有樣式的,就相當(dāng)于頁面中的內(nèi)容

 const eleHtml = document.querySelector('.zxksBody');

2、獲取打印容器的屬性

首先做個(gè)兼容判斷,判斷是否取到了DOM結(jié)點(diǎn)信息,如果取到了DOM結(jié)點(diǎn)就獲取DOM結(jié)點(diǎn)的內(nèi)容,進(jìn)行高度和寬度的賦值

 if (eleHtml) {
    let eleW = eleHtml.offsetWidth; // 獲得該容器的寬
    let eleH = eleHtml.offsetHeight; // 獲得該容器的高
 }

3、生成PDF

這一步就是把獲取到的DOM結(jié)點(diǎn),通過jsPDF和html2canvas 生成為PDF

html2canvas(eleHtml, {
        dpi: 300,
        width: eleW,
        height: eleH,
        scale: 2, // 提高渲染質(zhì)量
        useCORS: true  //允許canvas畫布內(nèi) 可以跨域請(qǐng)求外部鏈接圖片, 允許跨域請(qǐng)求。
      }).then(async (canvas) => {
            const pdf = new jsPDF('', 'pt', 'a4');
            const imgData = canvas.toDataURL('image/png', 1.0);
            //a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
            const imgWidth = 555.28;
            //一頁pdf顯示html頁面生成的canvas高度;
            const imgHeight = 555.28 / canvas.width * canvas.height;
            // 計(jì)算分頁
            const pageHeight = 841.89;
            //未生成pdf的html頁面高度
            let leftHeight = imgHeight;
            //頁面偏移
            let position = 0;

            if (leftHeight < pageHeight) {
              //在pdf.addImage(pageData, 'JPEG', 左,上,寬度,高度)設(shè)置在pdf中顯示
              pdf.addImage(imgData, 'PNG', 20, 20, imgWidth, imgHeight);
            } else { // 分頁
               while (leftHeight > 0) {
                  pdf.addImage(imgData, 'PNG', 20, position, imgWidth, imgHeight);
                  leftHeight -= pageHeight;
                  position -= 841.89;
                  if (leftHeight > 0) {
                      pdf.addPage();
                  }
               }
         });

4、保存本地或者上傳OSS

 保存本地

保存本地的話比較簡(jiǎn)單,直接調(diào)用PDF庫自帶的方法就可以保存到本地

pdf.save(`${state.xsMc}-${state.xsBh}.pdf`)

上傳OSS

上傳的OSS的話就比較復(fù)雜一點(diǎn),首先就是需要配置OSS的內(nèi)容,然后把PDF轉(zhuǎn)換為Blob對(duì)象,最后就是調(diào)用OSS的接口實(shí)現(xiàn)上傳。

// 配置OSS
const client = new OSS({
  region: "******",
  bucket: 'bucketName',
  endpoint: 'endpoint',
  stsToken: 'securityToken',
  accessKeyId: 'accessKeyId',
  accessKeySecret: 'accessKeySecret',
});


// 將 PDF 文件轉(zhuǎn)換為 Blob 對(duì)象
const pdfBlob = pdf.output('blob');

// 調(diào)用OSS上方實(shí)現(xiàn)上傳
const fileRes = await client.put(`${state.xsMc}-${state.xsBh}.pdf`, pdfBlob);
console.log(fileRes, '接收返回的OSS信息');

5、注意事項(xiàng)

  •  使用html2canvas和jsPDF可能會(huì)遇見文本錯(cuò)位或者樣式錯(cuò)誤問題,這個(gè)時(shí)候需要進(jìn)行調(diào)整,可以通過html2canvas中的onclone回調(diào)方法進(jìn)行調(diào)整
html2canvas(eleHtml, {
  onclone: (documentClone) => {
    // 在克隆的文檔上進(jìn)行修改
    const partRight2 = documentClone.querySelector('.partRight2');
    const titleBars = documentClone.querySelectorAll('.titleBar');

    if (partRight2) {
      partRight2.style.display = 'none'; // 隱藏內(nèi)容
    }
    if (titleBars) {
      //修改樣式屬性
      titleBars.forEach(titleBar => {
        titleBar.style.marginTop = '-8px';
        titleBar.style.marginBottom = '20px';
      });
    }
  },
  dpi: 300,
  width: eleW,
  height: eleH,
  scale: 2, // 提高渲染質(zhì)量
  useCORS: true  //允許canvas畫布內(nèi) 可以跨域請(qǐng)求外部鏈接圖片, 允許跨域請(qǐng)求。
}).then(async (canvas) => {
        .......
    });
  • 對(duì)于在獲取DOM時(shí),帶有滾動(dòng)條的內(nèi)容無法正確獲取他的高度和寬度,內(nèi)容可能會(huì)被遮蓋無法正確打印,這個(gè)時(shí)候需要在打印前更改頁面中的DOM樣式才能正確打印
// 獲取全部?jī)?nèi)容
const eleHtml = document.querySelector('.zxksBody');

// 在生成canvas之前就把樣式進(jìn)行更改,獲取盒子的正常高度或者寬度,防止樣式被遮蓋,
const changeHeight = document.querySelector('.zxksContent');

if (changeHeight) {
  changeHeight.style.height = '100%'; // 更改高度
}

html2canvas(eleHtml, {
    dpi: 300,
    width: eleW,
    height: eleH,
    scale: 2, // 提高渲染質(zhì)量
    useCORS: true  //允許canvas畫布內(nèi) 
 }).then(async (canvas) => {

        .....

        // 在打印完成后,再把樣式改回去
        if (changeHeight) {
           changeHeight.style.height = 'calc(100vh - 182px)';
        }
    }
  • 對(duì)于帶有滾動(dòng)條的div盒子,在點(diǎn)擊打印時(shí),最好把頁面內(nèi)容進(jìn)行更改,防止無法正確獲取盒子高度,導(dǎo)致文字被隱藏,在打印完成后,在更改回去

// 對(duì)于vue

可以使用v-if進(jìn)行更換,把展示的內(nèi)容保存在div中,去掉溢出滾動(dòng)功能

// 對(duì)于react

可以使用三元運(yùn)算符進(jìn)行判斷,展示的內(nèi)容

6、完整代碼

const printPdf = async () => {
       const client = new OSS({
              const client = new OSS({
              region: "******",
              bucket: 'bucketName',
              endpoint: 'endpoint',
              stsToken: 'securityToken',
              accessKeyId: 'accessKeyId',
              accessKeySecret: 'accessKeySecret',
        }); 
       try {
          // 獲取全部?jī)?nèi)容
          const eleHtml = document.querySelector('.zxksBody');
          // 帶有移除隱藏的功能
          const changeHeight = document.querySelector('.zxksContent');

          if (changeHeight) {
            changeHeight.style.height = '100%'; // 更改高度
          }

          if (eleHtml) {
            let eleW = eleHtml.offsetWidth; // 獲得該容器的寬
            let eleH = eleHtml.offsetHeight; // 獲得該容器的高

            // 確保獲取加載完全的DOM
            setTimeout(() => { 
              html2canvas(eleHtml, {
                onclone: (documentClone) => {
                  // 在克隆的文檔上進(jìn)行修改
                  const partRight2 = documentClone.querySelector('.partRight2');
                  const titleBars = documentClone.querySelectorAll('.titleBar');

                  if (partRight2) {
                    partRight2.style.display = 'none'; // 隱藏內(nèi)容
                  }
                  if (titleBars) {
                    titleBars.forEach(titleBar => {
                      titleBar.style.marginTop = '-8px';
                      titleBar.style.marginBottom = '20px';
                    });
                  }
                },
                dpi: 300,
                width: eleW,
                height: eleH,
                scale: 2, // 提高渲染質(zhì)量
                useCORS: true  //允許canvas畫布內(nèi) 可以跨域請(qǐng)求外部鏈接圖片, 允許跨域請(qǐng)求。
              }).then(async (canvas) => {
                const pdf = new jsPDF('', 'pt', 'a4');
                const imgData = canvas.toDataURL('image/png', 1.0);
                const imgWidth = 555.28;
                const imgHeight = 555.28 / canvas.width * canvas.height;

                // 計(jì)算分頁
                const pageHeight = 841.89;
                let leftHeight = imgHeight;
                let position = 0;

                if (leftHeight < pageHeight) {
                  pdf.addImage(imgData, 'PNG', 20, 20, imgWidth, imgHeight);
                } else {
                  while (leftHeight > 0) {
                    pdf.addImage(imgData, 'PNG', 20, position, imgWidth, imgHeight);
                    leftHeight -= pageHeight;
                    position -= 841.89;
                    if (leftHeight > 0) {
                      pdf.addPage();
                    }
                  }
                }

                // 將 PDF 文件轉(zhuǎn)換為 Blob 對(duì)象
                const pdfBlob = pdf.output('blob');
              
                // 使用 OSS 客戶端上傳 Blob 對(duì)象
                try {
                  const fileRes = await client.put(`${state.xsMc}-${statexsBh}.pdf`, pdfBlob);
                  console.log('client res', fileRes);
                } catch (err) {
                  console.error('PDF上傳失敗,請(qǐng)重新提交!', err);
                }

                if (changeHeight) {
                  changeHeight.style.height = 'calc(100vh - 182px)';
                }
              });
            }, 1000);
          }
        } catch (error) {
          console.log("Error!", error);
          if (changeHeight) {
            changeHeight.style.height = 'calc(100vh - 182px)';
          }
        }
      };

總結(jié) 

到此這篇關(guān)于純前端生成PDF(jsPDF)并下載保存或上傳到OSS的文章就介紹到這了,更多相關(guān) 前端生成PDF并下載保存或上傳到OSS內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論