纯前端如何实现批量下载功能呢?

纯前端如何实现批量下载功能呢?

***需求:***在不依赖后端的情况下,前端需要独立实现批量下载,且下载的文件需统一放在一个文件夹中并压缩
插件:

html2canvas可以实现截图功能

JsPDF 可以将文件生成pdf

JSZip 可以压缩文件

FileSaver 保存文件到本地

代码如下:

javascript 复制代码
<template>
  <div>
    <van-button @click="zipPdf">批量下载</van-button>
    <div
      v-for="(item, index) in pdfList"
      :key="index"
      id="downPdf"
      style="margin-bottom: 50px"
    >
      标题{{ index }}
      <div v-for="keys in 50" :key="keys">内容{{ keys }}</div>
    </div>
  </div>
</template>
javascript 复制代码
<script>
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
import JSZip from 'jszip';
import FileSaver from 'file-saver';
export default {
  name: 'zipPDF',
  data() {
    return {
      isShow: false,
      planName: '测试',
      pdfList: [
        {
          taskId: '001',
          taskName: '测试一',
          num: '1',
        },
        {
          taskId: '002',
          taskName: '测试二',
          num: '2',
        },
      ],
    };
  },
  methods: {
    htmlToPDF() {
      this.zipPdf();
    },
    //下载
    async zipPdf() {
      let allRefList = [];
      for (let index = 0; index < this.pdfList.length; index++) {
        let downPdfListRef = document.getElementById('downPdf');
        let title =
          this.pdfList[index].taskId + '-' + this.pdfList[index].taskName;
        const p = await this.getPdf(downPdfListRef, title);
        allRefList.push(p);
        console.log('现在生成第' + (index + 1) + '份pdf页面了');
        if (index === this.pdfList.length - 1) {
          this.zipChange(allRefList);
        }
      }
    },
    //转pdf
    getPdf(el, pdfName) {
      return new Promise((resolve) => {
        html2Canvas(el, {
          allowTaint: true,
          scale: 1, //处理模糊问题
          useCORS: true, //开启跨域,这个是必须的
        }).then(function (canvas) {
          //需要异步处理
          setTimeout(() => {
            let pdf = new JsPDF('p', 'mm', 'a4'), //A4纸,纵向
              ctx = canvas.getContext('2d'),
              a4w = 190,
              a4h = 247,
              imgHeight = Math.floor((a4h * canvas.width) / a4w),
              renderedHeight = 0;
            while (renderedHeight < canvas.height) {
              let page = document.createElement('canvas');
              page.width = canvas.width;
              page.height = Math.min(imgHeight, canvas.height - renderedHeight); //可能内容不足一页
              //用getImageData剪裁指定区域,并画到前面创建的canvas对象中
              page
                .getContext('2d')
                .putImageData(
                  ctx.getImageData(
                    0,
                    renderedHeight,
                    canvas.width,
                    Math.max(imgHeight, canvas.height - renderedHeight)
                  ),
                  0,
                  0
                );
              pdf.addImage(
                page.toDataURL('image/jpeg', 1.0),
                'JPEG',
                10,
                30,
                a4w,
                Math.min(a4h, (a4w * page.height) / page.width)
              );
              renderedHeight += imgHeight;
              if (renderedHeight < canvas.height) {
                pdf.addPage(); //如果后面还有内容,添加一个空页
              }
            }
            resolve({ PDF: pdf, name: pdfName });
            // PDF.save(pdfName + '.pdf')
          });
        });
      }, 500);
    },
    //压缩
    zipChange(data) {
      const zip = new JSZip();
      data.forEach(async (item) => {
        const { PDF, name } = item;
        if (data.length === 1) {
          PDF.save(`${name}.pdf`);
        } else {
          await zip.file(`${name}.pdf`, PDF.output('blob'));
        }
        if (data.length > 1) {
          zip.generateAsync({ type: 'blob' }).then((content) => {
            FileSaver.saveAs(content, this.planName + '.zip');
          });
        }
      });
    },
  },
};
</script>
相关推荐
朝阳58137 分钟前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter1 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友1 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry2 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉3 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog3 小时前
低端设备加载webp ANR
前端·算法
LKAI.3 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy4 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js