Node配合Vue实现压缩文件并在浏览器中下载(升级版)
之前我写了“Node实现压缩文件并下载”,那个是最基础的版本,这次升级版需求变了,需要选择一个文件然后传给Node,Node接收到在指定目录下找到需要下载的单个目录,而不是整个了,并且这次是多层目录。
注意:需要安装jszip包,npm install jszip
Vue端
<template>
<div>
<!-- 省略列表选择代码 -->
<button @click="downloadZip">Download Zip</button>
</div>
</template>
<script>
import { downloadFile } from '@/services/api'
export default {
data() {
// ...省略
},
methods: {
downloadZip() {
// 从 Node请求压缩文件,downloadFile是封装的接口,结合自己项目进行调整
// this.currentSelectLoadout.FileName是我们最后选择的文件名
downloadFile(this.currentSelectLoadout.FileName).then(res => {
window.location.href = `http://localhost:7001/download-zip?fileName=${this.currentSelectLoadout.FileName}`
})
}
}
}
</script>
Node端
路由界面
'use strict'
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const {router, controller} = app
router.get('/download-zip', controller.home.downloadZip)
}
controller层方法
async downloadZip() {
const { ctx } = this
// 先获取我们选择的文件名,也就是获取Vue端传来的this.currentSelectLoadout.FileName
const { fileName } = ctx.queryParams
const zip = new jszip()
// 获取指定目录数据
const folderPath = path.resolve(__dirname, `D:\\WorkSpace\\WarSim\\WarSim\\Analysis\\${fileName}\\`)
// 检查目录是否存在
if (fs.existsSync(folderPath)) {
// 如果存在目录则去递归压缩目录里的所有数据
this.addDirToZip(zip, folderPath)
} else {
console.log('下载目录不存在')
}
// 压缩整个文件
const zipContent = await zip.generateAsync({ type: 'nodebuffer' })
// 返回
const encodedFileName = encodeURIComponent(`${fileName}.zip`)
ctx.set('Content-Type', 'application/octet-stream')
ctx.set('Content-Disposition', `attachment; filename*=UTF-8''${encodedFileName}`)
ctx.body = zipContent // 发送压缩包内容
}
addDirToZip(zip, folderPath) {
// 先读首层目录有多少个,然后遍历循环读目录的子集
const files = fs.readdirSync(folderPath)
files.forEach(file => {
const fullPath = path.join(folderPath, file)
const stat = fs.statSync(fullPath)
if (stat.isDirectory()) {
// 如果是文件夹,则递归处理
const folderZip = zip.folder(file)
this.addDirToZip(folderZip, fullPath)
} else {
// 如果是文件,则直接添加
const content = fs.readFileSync(fullPath)
zip.file(file, content)
}
})
}