4

使用Vue3在浏览器端进行zip文件压缩 - Gods_巨蚁

 4 months ago
source link: https://www.cnblogs.com/gods/p/18168661
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

使用Vue3在浏览器端进行zip文件压缩

在前端开发中,我们时常需要处理文件上传和下载的功能。有时,用户可能希望将多个文件打包成一个zip文件以便于下载。我这里分享一个使用Vue3和JSZip库在浏览器端实现zip文件压缩的示例。

案例:https://anttoolbox.cn/tools/zip,这是个在线zip压缩工具,可以选择计算机本地文件,然后打包成一个zip包。我参与了该功能开发~~~

首先,我们需要安装JSZip库。如果你使用的是npm,可以通过以下命令进行安装:

npm install jszip

在Vue3组件中,我们可以定义一个响应式引用fileDatas来存储用户上传的文件信息。同时,我们还需要几个其他的引用来控制压缩选项和进度。

<script lang="ts" setup>
import { ref } from 'vue'
import JSZip from 'jszip'
import { saveAs } from 'file-saver' // 注意这里我假设你已经有file-saver库了

interface FileData {
  file: File
  fileName: string
}

const fileDatas = ref<FileData[]>([])
const isCompress = ref(false) // 是否启用压缩
const compressionLevel = ref(6) // 压缩级别
const packagingPercentage = ref(0) // 压缩进度

// 文件上传处理函数
const fileUpload = (file: File) => {
  fileDatas.value.push({
    file,
    fileName: file.name
  })
}

// 打包为zip文件
const packageAsZip = async () => {
  packagingPercentage.value = 0

  const zip = new JSZip()
  fileDatas.value.forEach((fileData) => {
    zip.file(fileData.fileName, fileData.file)
    packagingPercentage.value += 100 / fileDatas.value.length // 简化进度计算
  })

  let content: Blob

  if (isCompress.value) {
    content = await zip.generateAsync({
      type: 'blob',
      compression: 'DEFLATE',
      compressionOptions: { level: compressionLevel.value }
    })
  } else {
    content = await zip.generateAsync({ type: 'blob' })
  }

  saveAs(content, 'compressed_files.zip')
}
</script>

<template>
  <div>
    <!-- 假设你有一个文件上传组件CommonFileUploadWithDirectory -->
    <CommonFileUploadWithDirectory @upload="fileUpload" />

    <!-- 压缩按钮 -->
    <button @click="packageAsZip">压缩为ZIP</button>

    <!-- 文件列表展示 -->
    <div v-if="fileDatas.length > 0" class="file-list">
      <div v-for="(fileData, index) in fileDatas" :key="index" class="file-list-item">
        <!-- 假设你有一个删除按钮组件,这里用了一个简单的删除逻辑 -->
        <button @click="fileDatas.splice(index, 1)">删除</button>
        <span>{{ fileData.fileName }}</span>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 样式省略 */
</style>

在上面的代码中,我们定义了一个文件上传处理函数fileUpload,每当用户上传一个文件时,就将文件信息添加到fileDatas数组中。我们还定义了一个packageAsZip函数,该函数会遍历fileDatas数组中的每个文件,并使用JSZip将它们添加到zip文件中。然后,根据isCompress的值决定是否启用压缩,并生成一个Blob对象。最后,使用file-saver库的saveAs函数将Blob对象保存为zip文件。

注意,我在计算压缩进度时进行了简化,直接假设每个文件占据相等的进度。在实际应用中,你可能需要根据文件的大小或压缩的实际情况来更精确地计算进度。

实际案例:https://anttoolbox.cn/tools/zip,这里我参与了开发~~~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK