> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 多文件压缩下载

## 前言需求

近期开发后台管理系统时，有一个【 **批 量 下 载**】的业务需求。要求是：能批量下载用户提交的文件附件；后台用户列表展示的是前端用户的投稿信息记录，前端稿件投递都以附件的方式借助阿里云 OSS 直接上传至了云存储中，数据只是记录的用户上传附件的文件路径。

最初擦下载附件是采用“a”标签点击跳转的方式进行文件的下载和保存，但是此方式操作起来相对麻烦，为了实现后台管理员提出的要求，决定采用批量下载附件的方式来进行文件的重命名和压缩存储。此方式不仅解决了下载文件繁琐的问题，同时，还一并完善了下载文件重命名的问题。

## 安装插件

- [**jszip**](https://stuk.github.io/jszip/)


```sh [npm]
npm install jszip
```

```sh [yarn]
yarn add jszip
```

```sh [pnpm]
pnpm add jszip
```

```sh [bun]
bun add jszip
```

```sh [deno]
deno add npm:jszip
```

【 注 】：生成压缩文件，详细用法请点击上述超链接。

- [**file-saver**](https://github.com/eligrey/FileSaver.js#readme)


```sh [npm]
npm install file-saver
```

```sh [yarn]
yarn add file-saver
```

```sh [pnpm]
pnpm add file-saver
```

```sh [bun]
bun add file-saver
```

```sh [deno]
deno add npm:file-saver
```

【 注 】：保存文件用的，可以保存流文件、canvas、文本等。

## 使用方法

```javascript title="引入依赖"
import axios from "axios";
import JSZip from "jszip";
import { saveAs } from "file-saver";
```

```javascript title="生成文件流"
const getFile = (url) => {
    return new Promise((resolve, reject) => {
        axios
            .get(url, {
                responseType: "arraybuffer",
            })
            .then((res) => {
                resolve(res.data);
            })
            .catch((err) => {
                reject(err.toString());
            });
    });
};
```

注：此次需要借助 axios 将 URL 流文件转换为二进制流文件；在 vue 项目中，若使用绑定在 vue 上的 axios 实例，在请求生成 arraybuffer 文件时会报请求跨域的错误！！！

```javascript title="文件导出"
let list = [
    {
        name: "我是自定义文件名",
        url: "https://xxxxxxxxx.docx",
    },
];

// 创建JSZip实例
const zip = new JSZip(),
    // promise对象
    promises = [];
// 文件后缀名
let suffix = "";
list.forEach((el) => {
    // 获取文件后缀名
    suffix = el.url.substring(el.url.lastIndexOf("."));
    // 生成promise实例
    const promise = getFile(el.url).then((res) => {
        zip.file(el.name + suffix, res);
    });
    promises.push(promise);
});
// 异步处理
Promise.all(promises).then(() => {
    // 生成二进制流
    zip.generateAsync({
        type: "blob",
    }).then((content) => {
        saveAs(content, "压缩文件.zip");
        /* 保存文件 */
    });
});
```

注：此次是批量将 URL 格式的附件经过处理生成压缩包导出到本地。

## 补充（保存 URL 文件）

最初，保存 URL 类型的文件大多采用“a”标签跳转的形式进行下载和保存，有时前端请求流式文件生成文件时大多也是采用动态创建“a”标签的形式进行前端的文件下载。此方式相对来说，每次都要写一些动态创建标签的方法。当完成这次文件的批量导出时候，忽然想到“file-saver”的“saveAs”属性可以用来保存文件。

```javascript title="保存 URL 文件"
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })
```

:::info 注意
传递`{ autoBom: true }`如果你想 FileSaver.js 自动提供 Unicode 文本编码提示。请注意，只有在您的 Blob 类型已`charset=utf-8`设置的情况下才能执行此操作。

:::

## 总结

文件处理，在后台管理系统中还是比较常见的，使用的频率相对来说也是比较高的。此次笔记只为记录开发过程中遇到的问题以及处理问题的方法和思路。此次之所以会想到此中办法，主要是无意间翻看到了 **Angular** 的一个中文网站 [ng-alain](https://ng-alain.com/zh)，无意间在该网站的组件模块中看到了 zip 文件下载的组件。因此想着在 vue 项目中尝试着使用 jszip 等依赖来实现文件链接的批量打包下载以及文件的重命名保存等功能。
