前端JSZip批量下载视频压缩包

402 阅读1分钟

前言

有些时候,项目上需要前端在浏览器下载压缩包,压缩包里可能是多个视频、图片、excel,也可能是带嵌套层级的文件夹。此时,用JSZip 可轻松解决这些需求,具体api文档 大家可自行查阅,文档还是比较全面的。我下面主要介绍两种实际应用场景,这两种场景的思路都是一致的。

思路

  1. 利用 JSZip 对象的 filefolder 方法往对象里插入文件、文件夹
  2. 使用 generateAsync 方法拿到文件流,通常是blob格式
  3. 创建a标签,下载

场景一

下载目录文件夹

WX20221208-102032@2x.png

点击【下载目录】,需要把【2】处的树结构以文件夹的形式下载成压缩包

代码

import JSZip from 'jszip'
	
const treeData = [
    {
      packageName: '10月',
      childList: [
        {
          packageName: '10月1日'
        },
        {
          packageName: '10月2日'
        }
      ]
    },
    {
      packageName: '11月',
      childList: [
        {
          packageName: '11月11日'
        }
      ]
    }
  ]
  
  // 比较通用的下载方法
  function downloadBlob(blob, name = '') {
    const downloadElement = document.createElement('a')
    const href = window.URL.createObjectURL(blob) // 创建下载的链接
    downloadElement.href = `${href}`
    downloadElement.style.display = 'none'
    if (name) {
      downloadElement.download = `${name}` // 下载后文件名
    }
    document.body.appendChild(downloadElement)
    downloadElement.click() // 点击下载
    document.body.removeChild(downloadElement) // 下载完成移除元素
    window.URL.revokeObjectURL(href) // 释放掉blob对象
  }

  // 生成压缩包的主要方法
  const handleDownload = treeData => {
    const name = '文件夹压缩包'
    const zip = new JSZip()
    const first = zip.folder(name)
    // 插入空文件夹
    treeData.forEach(({ packageName, childList }) => {
      let sec = first.folder(packageName)
      childList.forEach(({ packageName }) => {
        sec.folder(packageName)
      })
    })
    zip.generateAsync({ type: 'blob' }).then(function (content) {
      const filename = `${name}.zip`
      downloadBlob(content, filename)
    })
  }
  
  handleDownload(treeData)

场景二

已有多个http的视频链接,批量下载视频压缩包

此场景下需要多增加一步操作,即通过视频链接(http远程链接)拿到blob文件

代码

以下方法为根据视频链接(http远程链接)拿到blob文件,请求用的是xhr,也可用fetch

function getVideoBlob(url) {
    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest()
      xhr.open('GET', url, true)
      xhr.responseType = 'blob' // 设置返回类型blob
      xhr.onload = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          let blob = this.response
          blob = new Blob([blob], {
            type: 'video/mp4'
          })
          resolve(blob)
        }
      }
      xhr.send()
    })
  }

以下为主方法

import JSZip from 'jszip'

async function downLoadVideoZip(url) {
  let blob = await getVideoBlob(url)
  const name = '视频包'
  var zip = new JSZip()
  var first = zip.folder(name)
  first.file('file.mp4', blob)
  zip.generateAsync({ type: 'blob' }).then(function (content) {
    var filename = `${name}.zip`
    downloadBlob(content, filename)
  })
}