将视频和图片同时下载到压缩包内

文章介绍了如何在layui框架下,利用jszip和FileSaver.js库处理后端返回的数据,实现用户选择的图片和视频的下载。通过Promise.all监控下载进度,并对内容进行压缩处理,最终以.zip文件形式保存。
摘要由CSDN通过智能技术生成

说明

做项目使用的layui搭建的后台

后端返回的数据结构

在这里插入图片描述

前端依赖插件

  1. Jszip https://cdn.bootcdn.net/ajax/libs/jszip/3.5.0/jszip.js
  2. FileSaver https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.2/FileSaver.js

注意, layui引入第三方组件 需要将第三方组件包裹

引入JSzip

文件路径

layui.define(function(exports){
	// ↓这里粘贴jszip的代码
	// ↑
	exports('jszip', new JSZip());
});

引入FileSaver

文件路径

layui.define(function(exports){
	// ↓这里粘贴FileSaver的代码
	// ↑
	exports('filesaver', saveAs);
}); 

页面加载第三方代码

layui.extend({
        jszip:'/static/js/jszip',
        filesaver:'/static/js/filesaver',
})
layui.use(['form', 'layer', 'jquery', 'layedit', 'upload','table','jszip','filesaver'],function(){
				var jszip = layui.jszip;
                var saveAs = layui.filesaver;
})

页面加入点击事件

<button class="layui-btn clockClick" >
                    下载打卡信息
  </button>
***
$(".clockClick").on("click",function(res){
                    var data = layui.table.checkStatus("dataTable").data; // 获取复选框选择的所有数据
                    console.log(data)
                    if(data.length == 0){
                        layer.msg("请选择信息");
                        return false;
                    }
  })

展示效果

在这里插入图片描述

主要代码部分

点击事件

$(".clockClick").on("click",function(res){
                    var data = layui.table.checkStatus("dataTable").data;
                    if(data.length == 0){
                        layer.msg("请选择信息");
                        return false;
                    }
                    jszip.remove("打卡记录"); // 清理掉之前文件
                    var index = layer.load(0, {shade: true}); //loading加载
                    var img = jszip.folder("打卡记录"); // 生成图片文件夹
                    
                    var pro = data.map(async (res,k)=>{
                        return new Promise(async (resolve, reject) =>{
                            var name = img.folder(res.student_name);
                            console.log(res, 'name')
                            var retImg,retVid = false;
                            if(res.image.length == 0){
                                console.log("空图片")
                                retImg =true;
                            }
                            if(res.video.length == 0){
                                console.log("空视频")
                                retVid = true;
                            }
                            res.image.map(async (imgItem,imgKey)=>{
                                var hui = await downImg(res, imgItem,name);
                                console.log("下载图片",res.id , imgKey, (res.image.length - 1) )
                                if(imgKey === (res.image.length - 1) ){
                                    console.log("成功")
                                    retImg = true;
                                }
                                
                                if(retImg && retVid){
                                    resolve(true)
                                }
                            })
                            res.video.map(async (videoItem,videoKey)=>{
                                var hui =await downVideo(res, videoItem, name);
                                console.log("下载视频",res.id)
                                if((res.video.length -1) === videoKey){
                                    retVid = true;
                                }
                                if(retImg && retVid){
                                    resolve(true)
                                }
                            })
                            
                            if(retImg && retVid){
                                resolve(true)
                            }
                        })
                    });
                    console.log(pro); // 此处打印用来查看控制台是否全部完成
                    Promise.all(
                        pro
                    ).then(() =>{
                        layer.closeAll('loading'); //关闭加载层
                        saveFile(); // 全部执行完 保存代码
                      console.log('结束')
                    }).catch((e) => {
                        layer.closeAll('loading'); //关闭加载层
                        layer.msg("下载失败");
                        console.error('结束',e)
                    })
                    return false;
                })

下载图片代码

function downImg(res, imgItem, name){
                     return new Promise(async (resolve, reject) =>{
                         const image = new Image()
                            image.setAttribute('crossOrigin', 'Anonymous') // 设置 crossOrigin 属性,解决图片跨域报错
                            //设置图片地址----稍后进行base64转换
                            image.src = imgItem
                            image.onload = () => {
                                const canvas = document.createElement('canvas')
                                // 让画布的宽高等于图片的宽高
                                canvas.width = image.width
                                canvas.height = image.height
                                // 然后在画布上进行画画
                                const ctx = canvas.getContext('2d')
                                    // 开始画图片,1.绘制的对象2.绘制的位置,3绘制的宽高
                                ctx.drawImage(image, 0, 0, image.width, image.height)
                                const url = canvas.toDataURL();
                                var img_arr = url.split(','); //分割开数据
                                name.file(res.tent+".png", img_arr[1], {base64:true});//图片批量写入文件
                                resolve(res.id)
                            }
                     })
                    
                }

下载视频代码

function downVideo(res, videoItem, name){
                    return new Promise(async (resolve, reject) =>{
                        videoItem = videoItem.replace(/http[^s]/i,"https:");
                        await xhrequest(videoItem).then((vres) => {
                              name.file( res.tent+'.mp4', vres, { Blob: true,})
                            resolve(res.id)
                         })
                    })
                }
                
                async function xhrequest(url) {
                    let data = await fetch(url, { mode: 'cors' })
                        .then((response) => response.blob())
                        .then((res) => {
                            return res
                        })
                    return data
                }

保存文件代码

function saveFile(){
                    jszip.generateAsync({
                        type:"blob", //压缩类型
            	        compression:"DEFLATE", //store:默认不压缩,defalte:需要压缩
            	        compressionOptions:{
            		        level:9  //压缩等级1--9, 1:压缩速度最快,9:最优压缩方式
            	        }
                    }).then(function(content) {
                        layer.closeAll('loading'); //关闭加载层
                        // see FileSaver.js
                        saveAs(content, "文件名.zip");
                    });
                }

感悟

其实最主要的用到的就是Promise来监听代码, Promise运行后 一直保持加载中的状态, 只有代码运行到resolve部分才会返回成功, 或者运行到reject 返回失败.
因为要下载多个视频和图片, 所以用Promise.all来监听多个
主要代码里面的retImg , retVid 用来一次次的遍历 每条数据内的视频数组和图片数组遍历完毕, 如果都完毕了 才会返回成功
当所有被选择的数据都返回成功后, 才会走到Promise.allthen

参考

各种视频,图片转换参考自

https://blog.csdn.net/WoNiuDeXiaYiYe/article/details/127051493

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏范霖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值