nodejs多层目录多文件压缩zip压缩包返回给前端(附demo)

1,452 阅读3分钟

nodejs多层目录多文件压缩zip压缩包返回给前端(附demo)

开源

个人开源的leno-admin后台管理项目,前端技术栈:reactHooksant-design;后端技术栈:koamysqlredis,整个项目包含web端electron客户端mob移动端template基础模板,能够满足你快速开发一整套后台管理项目;如果你觉得不错,就为作者点个✨star✨吧,你的支持就是对我最大的鼓励;

演示地址

文档地址

源码github地址

一、使用nodejs原生archiver方法生成压缩包

nodejs中自带的fs可操作文件和目录,archive可进行目录和文件的压缩,下面就来看下如何使用吧!

// 生成压缩包
export const batchGenCodeMid = async (ctx: Context, next: () => Promise<void>) => {
  try {
    // 压缩刚刚创建的代码文件
    const filePaths = ['src\node', 'src\react']
    
    // 先创建一个可写流,用于传入压缩包数据
    const output = fs.createWriteStream('leno-admin.zip')
    
    // 创建一个archive实例,就是一个可读流,可以指定压缩格式和压缩等级:压缩格式支持zip和tar,
    // 压缩等级速度最快的为1,即是不压缩,9的话是压缩性能最好。
    const archive = archiver('zip', {
      zlib: { level: 9 } 
    })
    
    // 用于监听 `archive` 对象上发生的特定事件。用于监听 `archive` 对象上的 `error` 事件。
    archive.on('error', function (err) {
      if (err) err
    })
    
    // 使用pipe将两个流连接,开始写压缩包数据
    archive.pipe(output)
    for (const i of filePaths) {
      // directory方法是压缩目录,可以传两个参数:第一个参数是源目录路径,第二个参数是文件夹在压缩包
      // 里面的目录路径,如果第二个参数为false的话,则就是压缩包内部不会新建目录
      archive.directory(i, 'leno-admin' + i.split('')[1])
    }
    // 生成完后将zip文件删除,需要主义的是该监听方法应该写于调用finalize之前
    output.on('close', () => {
      fs.unlinkSync('leno-admin.zip')
      // 删除之前生成用于压缩的文件
      filePaths.forEach((path) => {
        // 封装的删除目录及其内部所有目录文件的公用方法
        removeFolder(path)
      })
    })
    // 最后使用finalize进行压缩
    archive.finalize()
    // 压缩包直接是存在archive上,直接将archive返回给返回端即可
    ctx.state.buffer = archive
​
    await next()
  } catch (error) {
    console.error('生成压缩包', error)
    return ctx.app.emit('error', sqlErr, ctx)
  }
}

仅仅只压缩文件

// 使用Buffer生成一个文件,用于测试
const buffer = Buffer.from("let test = 11")
​
// 单个文件的压缩,可以使用append方法来对文件进行逐个添加。append方法第一个参数是source,
// 接收参数可以是string,buffer,stream;第二个参数为设置文件信息,name为指定文件的名称
archive.append(buffer,{name:'index.js'})

二、删除目录及其内部所有目录文件

/**
 * 删除文件夹及文件内所有的文件夹及文件
 * @param folderPath
 */
export const removeFolder = (folderPath: string) => {
  // 查询文件夹下面的所有文件
  const files = fs.readdirSync(folderPath)
​
  for (let item of files) {
    const stats = fs.statSync(`${folderPath}${item}`)
    // 检查是否为文件夹
    if (stats.isDirectory()) {
      // 为文件夹就递归
      removeFolder(`${folderPath}${item}`)
    } else {
      // 为文件就用删除文件方式删除
      fs.unlinkSync(`${folderPath}${item}`)
    }
  }
  // 文件夹内部文件删除完后,就用删除文件夹的方式删除文件夹
  fs.rmdirSync(folderPath)
}

三、前端接收函数封装

/**
 * 通用下载方法
 * @param url 请求地址
 * @param fileName 下载的文件名
 * @param fileFormat 下载的文件格式
 * @param params 请求传参
 * @returns buffer
 */
export function download(
  url: string,
  fileName: string,
  fileFormat: string = 'xlsx',
  params?: object,
) {
  return instance
    .post(url, params, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      responseType: 'blob',
    })
    .then(async (res: any) => {
      let uploadExcel = (fileName: any) => {
        const blob = new Blob([res.data], {
          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
        }) as any
        const url = URL.createObjectURL(blob)
        const aLink = document.createElement('a')
        aLink.setAttribute('download', fileName)
        aLink.setAttribute('href', url)
        document.body.appendChild(aLink)
        aLink.click()
        document.body.removeChild(aLink)
        URL.revokeObjectURL(blob)
      }
      uploadExcel(`${fileName}_${new Date().valueOf()}.${fileFormat}`)
    })
    .catch((r) => {
      console.error(r)
      message.error('下载文件出现错误,请联系管理员!')
    })
}

结语

以上是nodejs项目中设计多目录及多文件的压缩,该功能是个人自己写的开源项目里面的,如果有兴趣可以关注关注~开源项目地址,项目还在开发中,希望大家多多支持~谢谢🎉