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

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

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

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>
相关推荐
anOnion29 分钟前
构建无障碍组件之Menu Button pattern
前端·html·交互设计
用户47949283569151 小时前
claude Fable用不了?把Gpt 5.5pro接到你的claude code里
前端·后端
JieE2121 小时前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
冬奇Lab3 小时前
AI Workflow 定义的四次演进:从 Markdown 到 JS 脚本,再到分布式多 Agent
javascript·人工智能·agent
zhangxingchao3 小时前
Kotlin常用的Flow 操作符整理
前端
IT_陈寒5 小时前
React的useState居然还有这种坑?我差点删库跑路
前端·人工智能·后端
Pedantic6 小时前
SwiftUI 手势笔记
前端·后端
橙子家6 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user20585561518137 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州7 小时前
CSS aspect-ratio 属性完全指南
前端