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

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

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

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>
相关推荐
YaeZed4 分钟前
Vue3-watchEffect
前端·vue.js
boombb5 分钟前
H5 图片路径不统一,导致线上部分图片无法按预期展示(assetPrefix 与 basePath 行为不一致)
前端
栀秋6666 分钟前
深入浅出AI流式输出:从原理到Vue实战实现
前端·vue.js·前端框架
柳成荫7 分钟前
Chromium 渲染机制
前端
UIUV9 分钟前
JavaScript流式输出技术详解与实践
前端·javascript·代码规范
weixin_462446239 分钟前
PyQt 与 Flask 融合:实现桌面端一键启动/关闭 Web 服务的应用
前端·flask·pyqt
Hy行者勇哥10 分钟前
Edge 网页长截图 + 网站安装为应用 完整技术攻略*@
前端·edge
ujainu15 分钟前
Flutter入门:Dart基础与核心组件速成
javascript·flutter·typescript
Dreamboat-L17 分钟前
VUE使用前提:安装环境(Node.js)
前端·vue.js·node.js
吃好喝好玩好睡好18 分钟前
OpenHarmony混合开发:Flutter+Electron实战
javascript·flutter·electron