思路: 用 ajax 将文件下载, 然后用 jszip 压缩文件, 最后用 file-saver 生成文件

1. 准备工作

安装 3 个依赖: axios, jszip, file-saver

yarn add axios
yarn add jszip
yarn add file-saver

2. 下载文件

import axios from 'axios'
const getFile = url => {
    return new Promise((resolve, reject) => {
        axios({
            method:'get',
            url,
            responseType: 'arraybuffer'
        }).then(data => {
            resolve(data.data)
        }).catch(error => {
            reject(error.toString())
        })
    })
}

这里需要注意的是responseType, 如果下载文件是文本类型的(如: .txt, .js之类的), 那么用responseType: 'text'也可以, 但是如果下载的文件是图片, 视频之类的, 就得用arraybuffer

3. 打包文件

import JSZip from 'jszip'
import FileSaver from 'file-saver'
export default {
    methods: {
        handleBatchDownload() {
            const data = ['各类地址1', '各类地址2'] // 需要下载打包的路径, 可以是本地相对路径, 也可以是跨域的全路径
            const zip = new JSZip()
            const cache = {}
            const promises = []
            data.forEach(item => {
                const promise = getFile(item).then(data => { // 下载文件, 并存成ArrayBuffer对象
                    const arr_name = item.split("/")
                    const file_name = arr_name[arr_name.length - 1] // 获取文件名
                    zip.file(file_name, data, { binary: true }) // 逐个添加文件
                    cache[file_name] = data
                })
                promises.push(promise)
            })

            Promise.all(promises).then(() => {
                zip.generateAsync({type:"blob"}).then(content => { // 生成二进制流
                    FileSaver.saveAs(content, "打包下载.zip") // 利用file-saver保存文件
                })
            })
        },
    },
}

4. 最终代码

import axios from 'axios'
import JSZip from 'jszip'
import FileSaver from 'file-saver'

const getFile = url => {
    return new Promise((resolve, reject) => {
        axios({
            method:'get',
            url,
            responseType: 'arraybuffer'
        }).then(data => {
            resolve(data.data)
        }).catch(error => {
            reject(error.toString())
        })
    })
}

export default {
    render(h) {
        return (<a on-click={ () => this.handleBatchDownload() } href="javascript:;">批量下载</a>)
    },
    methods: {
        handleBatchDownload() {
            const data = ['各类地址1', '各类地址2'] // 需要下载打包的路径, 可以是本地相对路径, 也可以是跨域的全路径
            const zip = new JSZip()
            const cache = {}
            const promises = []
            data.forEach(item => {
                const promise = getFile(item).then(data => { // 下载文件, 并存成ArrayBuffer对象
                    const arr_name = item.split("/")
                    const file_name = arr_name[arr_name.length - 1] // 获取文件名
                    zip.file(file_name, data, { binary: true }) // 逐个添加文件
                    cache[file_name] = data
                })
                promises.push(promise)
            })

            Promise.all(promises).then(() => {
                zip.generateAsync({type:"blob"}).then(content => { // 生成二进制流
                    FileSaver.saveAs(content, "打包下载.zip") // 利用file-saver保存文件
                })
            })
        },
    },
}

注意:

如果下载的文件过大, 打包的时间将会很长, 甚至可能会导致浏览器奔溃

发表评论
huashang
包过大,浏览器崩溃怎么解决?
咸鱼
很好,代码复制下来直接就能用,嘿嘿嘿
hcccc
回复 @cwzl: 你好 请问跨域问题解决了嘛
hcccc
回复 @undefined: 请问跨域解决了嘛
wanwan1219
敢问博主自己试过吗?图片视频跨域问题怎么解决的呢?
zdjtry
打包下载出来的图片打开时提示无效的格式是为什么呢
cwzl
不是,先抛开打包下载问题,就getFile 方法图片跨域访问问题怎么解决
stone
回复 @凡间书生: 我也试了一下, 好像只是图片的后缀名没加上
凡间书生
希望您看到评论能为我解答,感谢
凡间书生
你确定这个方法可以下载图片么?我测试出来怎么不行