vue批量下载二维码图片并压缩

401 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

需求:因为需要后端生成二维码然后在前端进行导出,支持单个导出和批量导出

补充:因为我请求的是在 oss 上下载图片,然后因为请求协议的问题报以下错误,一般都是因为我们的网站是HTTPS的,而对方的链接是HTTP协议的,因此在Ajax或者javascript请求时,就会报如下这种错误:

错误.png

1. 单个导出的话我就简单带过了,主要是写一下批量的

// 单个有url的oss链接,直接下载的话  
FileSaver.saveAs(list[0].qr_code,`${list[0].title}.jpg`) // 通过fileSaver导出下载图片
  1. FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })

saveAs 方法支持三个参数,第一个参数表示它支持 Blob/File/Url 三种类型,第二个参数表示文件名(可选),而第三个参数表示配置对象(可选)。如果你需要 FlieSaver.js 自动提供 Unicode 文本编码提示(参考:字节顺序标记),则需要设置 { autoBom: true}

2. 批量导出

代码解释的话,主要在代码里面,方便更好的理解

//数据
 imgesArr:[
                {
                    url:'http://jingshipeihu.oss-cn-hangzhou.aliyuncs.com/patrol_code/20220630/ff02cca980ecd44887f0970f529847ca.jpg',
                    name:'first'
                },
                {
                    url:'http://jingshipeihu.oss-cn-hangzhou.aliyuncs.com/patrol_code/20220630/610dff0dd546a831dc11376a251580e5f.jpg',
                    name:'second'
                }
            ]
// 逻辑
 // 下载二维码图片并压缩
        getImgArrayBuffer(url){
            return new Promise((resolve,reject) => {
                //通过请求获取文件blob格式
                let xmlHTTP = new XMLHttpRequest()
                xmlHTTP.open('GET',url,true)
                xmlHTTP.responseType = "blob";
                xmlHTTP.onload = function() {
                    if(this.status == 200 ){
                        // console.log(this.response)
                        resolve(this.response)
                    }else{
                        // console.log(this.status)
                        reject(this.status)
                    }
                }
                xmlHTTP.send()
            }) 
        },
        // 批量下载
         batchDownload(){
            let zip = new JSZip() // 进行压缩
            var imgObj = {} // 创建一个对象保存遍历的要下载的图片
            let promises = [] // 创建一个数组,保存上面的下载图片的对象
            for(let obj of this.imgesArr){
                const promise =  this.getImgArrayBuffer(obj.url).then(data => {
                    zip.file(obj.name + '.png', data , {binary:true}); // 逐个添加文件
                    imgObj[obj.name] = data
                })
                promises.push(promise)
            }
            
            this.$message('正在压缩,请稍后!')
            // 使用promised.all 方法来实现,有可能会有点问题
            Promise.all(promises).then(async () => { 
    
                try {
                    const content =  await zip.generateAsync({type:'blob'}) // zip自带的方法,类型为blob,因为在要下载的时候上面转为了blob,兼容性更强
                    // console.log(content)
                    await FileSaver.saveAs(content,'压缩图片')
                    this.$message("压缩完成") 
                } catch (error) {
                    console.log(error)
                }
                // zip.generateAsync({type: 'blob'}).then(content => {
                //     this.$message('正在压缩,请稍后!')
                //     console.log(content)
                //     FileSaver.saveAs(content,'压缩图片') // 利用file-saver保存文件  自定义文件名
                //     this.$message("压缩完成")
                // }).catch(res => {
                //     console.log(111111)
                //     console.log(res)
                // })
            })
        }
    }

2.1 Promise.all 方法

Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且只返回一个Promise实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。

const p = Promise.all([p1, p2, p3]); 

p的状态由p1、p2、p3决定,分成两种情况:

  1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
MDN解释:

完成(Fulfillment):
如果传入的可迭代对象为空,Promise.all 会同步地返回一个已完成(resolved)状态的promise
如果所有传入的 promise 都变为完成状态,或者传入的可迭代对象内没有 promisePromise.all 返回的 promise 异步地变为完成。
在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组,它包含所有的传入迭代参数对象的值(也包括非 promise 值)。

失败/拒绝(Rejection):
如果传入的 promise 中有一个失败(rejected),Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成。

注意 ### Promise.all 的快速返回失败行为

Promise.all 在任意一个传入的 promise 失败时返回失败。例如,如果你传入的 promise中,有四个 promise 在一定的时间之后调用成功函数,有一个立即调用失败函数,那么 Promise.all 将立即变为失败。

如果作为参数的 Promise实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。

3. 封装的方法😌 为了复用,

(为了方便以后忘了直接拿来用 哈哈哈才不是勒)

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

// 单个二维码导出
export const singleExportQRCode = (url,name ) =>{
    // console.log(url)
    // console.log(name)
    if(!name){
        FileSaver.saveAs(url)  // 未传入导出图片名称
    }else{
        FileSaver.saveAs(url,`${name}.jpg`) // 通过fileSaver导出下载图片
    }
}


// 下载二维码图片并压缩
 function getImgArrayBuffer (url){
    return new Promise((resolve,reject) => {
        //通过请求获取文件blob格式
        let xmlHTTP = new XMLHttpRequest()
        xmlHTTP.open('GET',url,true)
        xmlHTTP.responseType = "blob";
        xmlHTTP.onload = function() {
            if(this.status == 200 ){
                // console.log(this.response)
                resolve(this.response)
            }else{
                // console.log(this.status)
                reject(this.status)
            }
        }
        xmlHTTP.send()
    }) 
}
// 批量二维码导出
export const  batchExportQRCode = list => {
    let zip = new JSZip()
    var imgObj = {}
    let promises = []
    for(let obj of list){
        const promise =  getImgArrayBuffer(obj.qr_code).then(data => {
            zip.file(obj.title + '.jpg', data , {binary:true}); // 逐个添加文件
            imgObj[obj.title] = data
        })
        promises.push(promise)
    }
    // console.log(promises)
    Promise.all(promises).then(async () => {
        try {
            const content =  await zip.generateAsync({type:'blob'})
            await FileSaver.saveAs(content,'压缩图片')
            // const newDate = +new Date()
            // console.log('new-',newDate)
        } catch (error) {
            console.log(error)
        }
    })
}