zip压缩与解压功能的实现

2 篇文章 0 订阅
1 篇文章 0 订阅

最近在做一个压缩zip,又解压zip的功能。需求是这样的:如下图所示,
1、红色框框里都是需要打包的东西,需要2个zip包,一个android,一个ios,点击两个绿色按钮开始压缩;
2、压缩包zip里面解压后是1个大文件夹,大的文件夹里面包含4个文件夹,分别为1个u3d(ios或android)模型文件夹(u3d)、1个背景图文件夹(bg)、1个人物图文件夹(gif)和1个展会切换图文件夹(switchover),如图二显示;
3、bg文件夹和gif文件夹里面的图片是根据蓝色框框中的数量动态改变的,需要全部图片上传后才可压缩;
4、把大的文件夹压缩成zip文件后,上传到oss,把得到的路径在绿色按钮旁边的input框中显示,并在保存的时候传给服务端;
5、编辑的时候再次点开,服务端会把zip的地址返给前端,此时,前端根据拿到的地址,解压,把文件依次渲染在页面上,如图三所示

在这里插入图片描述

文件路径
在这里插入图片描述

下面是实现思路:
1、首先,new一个全局zip实例a_zipBar,再利用这个实例新建一个全局文件夹变量a_folder(一式两份,a代表android,i代表ios)
2、其次,上传u3d模型的时候,用a_folder文件夹新建一个u3d文件夹;
3、其次,上传背景图的时候,用a_folder文件夹新建一个bg文件夹,把图片一次添加进去;
4、其次,上传人物图的时候,用a_folder文件夹新建一个gif文件夹,把图片一次添加进去;
5、再次,上传展会切换图的时候,用a_folder文件夹新建一个switchover文件夹;
6、最后,压缩a_folder文件夹,格式为zip,上传

下面是实现过程,压缩较为简单,解压过程较复杂

1、首先是根据蓝色框框内的数量,动态改变图片的数量

watch: {
  "currentRow.diamondCount"(newValue, oldValue) {
    //监听钻石展位
    newValue ? "" : (newValue = 0);
    oldValue ? "" : (oldValue = 0);
    this.getImageList(this.currentRow.diamondCount, "diamondCount", newValue, oldValue, true);
  },
  "currentRow.platinumCount"(newValue, oldValue) {
    //监听铂金展位
    newValue ? "" : (newValue = 0);
    oldValue ? "" : (oldValue = 0);
    this.getImageList(this.currentRow.platinumCount, "platinumCount", newValue, oldValue, false);
  },
  "currentRow.goldCount"(newValue, oldValue) {
    //监听黄金展位
    newValue ? "" : (newValue = 0);
    oldValue ? "" : (oldValue = 0);
    this.getImageList(this.currentRow.goldCount, "goldCount", newValue, oldValue, false);
  }
},
//新增展会图片列表数据的添加与删除
getImageList(inputLen, type, newValue, oldValue) {
  let diamondCount = this.currentRow.diamondCount;
  let platinumCount = this.currentRow.platinumCount;
  let goldCount = this.currentRow.goldCount;
  let diffCount = Math.abs(newValue - oldValue);
  // array.splice(2, 0, "three");  // 拼接函数(索引位置, 要删除元素的数量(0为不删除), 新增的元素)
  if (newValue > oldValue) {
    //
    if (type === "diamondCount") {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(oldValue + i, 0, {bgImage: "", personImage: ""});
      }
    } else if (type === "platinumCount") {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(diamondCount + oldValue + i, 0, {bgImage: ""});
      }
    } else {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(diamondCount + platinumCount + oldValue + i, 0, {bgImage: ""});
      }
    }
  } else if (newValue < oldValue) {
    // array.splice(2, 1);
    if (type === "diamondCount") {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(oldValue - i - 1, 1);
      }
    } else if (type === "platinumCount") {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(diamondCount + oldValue - i - 1, 1);
      }
    } else {
      for (let i = 0; i < diffCount; i++) {
        this.imageList.splice(diamondCount + platinumCount + oldValue - i - 1, 1);
      }
    }
  }
},

2、其次,上传u3d模型、背景图、人物图和展会切换图

//上传展会切换图
uploadSwitch(event) {
  let file = event.file;
  let fileType = 1; // 图片1,音频2,视频3,文件4
  let str = file.type.split("/")[1];
  uploadApi.upLoad.uploader(file, fileType).then((res) => {
    if (this.title === "新增") {
      this.currentRow.switchover = res.url;
      a_U3d.folder("switchover").file("switchover." + str, file, {base64: true});
      i_U3d.folder("switchover").file("switchover." + str, file, {base64: true});
    } else if (this.title === "编辑") {
      this.currentRow.switchover = res.url;
      this.$refs.formRef.$forceUpdate();
      for (let i in edit_i_U3d.files) {
        let imgName = edit_i_U3d.files[i].name; //获取文件名
        let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
        imgName = imgName.substring(imageIndex + 1, imgName.length);
        if (imgName === "switchover.png") {
          //如果文件名一致,则替换掉原有图片
          delete edit_i_U3d.files[i];
          edit_i_U3d
            .folder("i_shanghai_map")
            .folder("switchover")
            .file("switchover.png", event.file, {base64: true});
        }
      }
      for (let i in edit_a_U3d.files) {
        let imgName = edit_a_U3d.files[i].name; //获取文件名
        let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
        imgName = imgName.substring(imageIndex + 1, imgName.length);
        if (imgName === "switchover.png") {
          //如果文件名一致,则替换掉原有图片
          delete edit_a_U3d.files[i];
          edit_a_U3d
            .folder("a_shanghai_map")
            .folder("switchover")
            .file("switchover.png", event.file, {base64: true});
        }
      }
    }
  });
},
// U3D资源包
compressZip(file, type) {
  if (this.title === "新增") {
    if (type === "ios") {
      i_U3d.folder("u3d").file("u3d", file);
    } else {
      a_U3d.folder("u3d").file("u3d", file);
    }
  } else if (this.title === "编辑") {
    for (let i in edit_i_U3d.files) {
      let imgName = edit_i_U3d.files[i].name; //获取文件名
      let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
      imgName = imgName.substring(imageIndex + 1, imgName.length);
      if (imgName === "u3d") {
        //如果文件名一致,则替换掉原有u3d模型
        delete edit_a_U3d.files[i];
        edit_i_U3d.folder("u3d").file("u3d", file);
      }
    }
    for (let i in edit_a_U3d.files) {
      let imgName = edit_a_U3d.files[i].name; //获取文件名
      let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
      imgName = imgName.substring(imageIndex + 1, imgName.length);
      if (imgName === "u3d") {
        //如果文件名一致,则替换掉原有u3d模型
        delete edit_a_U3d.files[i];
        edit_a_U3d.folder("u3d").file("u3d", file);
      }
    }
  }
},
// 上传背景图或展厅人物图
onClickUploadImageHandle(event, index, type) {
  let file = event.file;
  let fileType = 1; // 图片1,音频2,视频3,文件4
  let suffix = file.name.split(".")[1]; //图片后缀
  uploadApi.upLoad.uploader(file, fileType).then((res) => {
    if (type === "bgImage") {
      if (this.title === "新增") {
        this.imageList[index].bgImage = res.url;
        a_U3d.folder("bg").file(index + 1 + "." + suffix, event.file, {base64: true});
        i_U3d.folder("bg").file(index + 1 + "." + suffix, event.file, {base64: true});
      } else if (this.title === "编辑") {
        this.$set(this.imageList[index], "bgImage", res.url);
        for (let i in edit_i_U3d.files) {
          let imgName = edit_i_U3d.files[i].name; //获取文件名
          let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
          imgName = imgName.substring(imageIndex + 1, imgName.length);
          if (imgName === index + 1 + ".png") {
            //如果文件名一致,则替换掉原有图片
            delete edit_i_U3d.files[i];
            edit_i_U3d
              .folder("i_shanghai_map")
              .folder("bg")
              .file(index + 1 + "." + suffix, event.file, {base64: true});
          }
        }
        for (let i in edit_a_U3d.files) {
          let imgName = edit_a_U3d.files[i].name; //获取文件名
          let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
          imgName = imgName.substring(imageIndex + 1, imgName.length);
          if (imgName === index + 1 + ".png") {
            //如果文件名一致,则替换掉原有图片
            delete edit_a_U3d.files[i];
            edit_a_U3d
              .folder("a_shanghai_map")
              .folder("bg")
              .file(index + 1 + "." + suffix, event.file, {base64: true});
          }
        }
      }
    } else {
      if (this.title === "新增") {
        this.imageList[index].personImage = res.url;
        a_U3d.folder("gif").file(index + 1 + ".gif", event.file, {base64: true});
        i_U3d.folder("gif").file(index + 1 + ".gif", event.file, {base64: true});
      } else if (this.title === "编辑") {
        this.$set(this.imageList[index], "personImage", res.url);
        this.$refs.formRef.$forceUpdate();
        for (let i in edit_i_U3d.files) {
          let imgName = edit_i_U3d.files[i].name; //获取文件名
          let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
          imgName = imgName.substring(imageIndex + 1, imgName.length);
          if (imgName === index + 1 + ".gif") {
            //如果文件名一致,则替换掉原有图片
            delete edit_i_U3d.files[i];
            edit_i_U3d
              .folder("i_shanghai_map")
              .folder("gif")
              .file(index + 1 + "." + suffix, event.file, {base64: true});
          }
        }
        for (let i in edit_a_U3d.files) {
          let imgName = edit_a_U3d.files[i].name; //获取文件名
          let imageIndex = imgName.lastIndexOf("\/"); //截取字符串最后一个/后面的所有字符
          imgName = imgName.substring(imageIndex + 1, imgName.length);
          if (imgName === index + 1 + ".gif") {
            //如果文件名一致,则替换掉原有图片
            delete edit_a_U3d.files[i];
            edit_a_U3d
              .folder("a_shanghai_map")
              .folder("gif")
              .file(index + 1 + "." + suffix, event.file, {base64: true});
          }
        }
      }
    }
  });
},

压缩:

<el-button @click="handleExpress("a_shanghai_map")">点击压缩Android</el-button>
<el-button @click="handleExpress("i_shanghai_map")">点击压缩IOS</el-button>
<script>
import JSZip from "jszip";
import {getOssToken} from "@/api/baseInfo";
//新增
let a_zip = new JSZip();
let i_zip = new JSZip();
let a_U3d = a_zip.folder("a_shanghai_map");
let i_U3d = i_zip.folder("i_shanghai_map");
// 编辑
let edit_a_zip = new JSZip();
let edit_i_zip = new JSZip();
let edit_a_U3d = a_zip.folder("a_shanghai_map");
let edit_i_U3d = i_zip.folder("i_shanghai_map");

export default {
	data() {
		return {}
	},
	methods: {
		 //压缩
	    handleExpress(name) {
	      if (this.resourceLen && this.isBgImage && this.isPersonImage) {
	        if (name === "i_shanghai_map") {
	          this.isPercentShow.ios = true;
	        } else {
	          this.isPercentShow.android = true;
	        }
	        let type = "";
	        if (this.title === "新增") {
	          type = name === "i_shanghai_map" ? i_zip : a_zip;
	        } else if (this.title === "编辑") {
	          type = name === "i_shanghai_map" ? edit_i_U3d : edit_a_U3d;
	        }
	        let timestamp = new Date().valueOf(); //时间戳
	        type.generateAsync({type: "blob"}).then((blob) => {
	          let files = new File([blob], timestamp + "-" + name, {type: "zip"});
	          this.uploader(blob, files, name).then((res) => {
	            let url = aliOssUrl + res.name;
	            if (name === "i_shanghai_map") {
	              this.currentRow.iOSResource = url;
	              this.currentRow.iOSResourceSize = files.size;
	              this.isPercentShow.ios = false;
	            } else {
	              this.currentRow.androidResource = url;
	              this.currentRow.androidResourceSize = files.size;
	              this.isPercentShow.android = false;
	            }
	          });
	        });
	      } else {
	        this.$message.warning("请完善资源包信息");
	      }
	    },
	    //oss分片上传
	    uploader(blob, files, name) {
	      return getOssToken({type: 4}).then((res) => {
	        const Oss = require("ali-oss");
	        const client = new Oss({
	          region: res.region,
	          secure: true,
	          accessKeyId: res.accessKeyId,
	          accessKeySecret: res.accessKeySecret,
	          stsToken: res.securityToken,
	          bucket: res.bucket,
	          endpoint: res.endpoint
	        });
	        let key = "";
	        key = res.dir + "/" + files.name;
	        this.percentageIos = 0;
	        this.percentageAndroid = 0;
	        return client.multipartUpload(key, blob, {
	          progress: (p, checkpoint) => {
	            if (name === "i_shanghai_map") {
	              this.percentageIos = Math.floor(p * 100);
	            } else {
	              this.percentageAndroid = Math.floor(p * 100);
	            }
	          }
	        });
	      });
	    },
	}
}
</script>

api/baseInfo.js文件

import request from "@/utils/request";

// 获取oss临时凭证
export function getOssToken(params) {
  return request({
    url: "/admin/base/getOssToken",
    method: "get",
    params
  });
}

解压:
点击编辑按钮的时候,弹窗出现,开始解压,文件越大,解压过程越久,因此,解压前在弹窗用loading加载

<el-button @click="handleEdit(url)">编辑</el-button>
<script>
export default {
	data() {
		return {
			title: "" 
		}
	},
	methods: {
		handleEdit(url) {
		    this.unzipLoading = true;
	        this.title = "编辑";
	        this.currentRow = Object.assign({}, row);
	        this.currentStatus = row.status;
	        this.currentRow.startTime = formatDate(this.currentRow.startTime);
	        this.currentRow.endTime = formatDate(this.currentRow.endTime);
	        this.currentRow.smsAlertTime = formatDate(this.currentRow.smsAlertTime);
	        this.lookEditDetailDialog = true;
	        let zipObjIos = await this.unZip(this.currentRow.iOSResource);
	        let zipObjAndroid = await this.unZip(this.currentRow.androidResource);
	        this.imageList = [];
	        console.log("解压", zipObjIos.bgArr);
	        for (let i = 0; i < zipObjIos.bgArr.length; i++) {
	          this.imageList.push({
	            bgImage: zipObjIos.bgArr[i]
	          });
	        }
	        for (let i = 0; i < this.currentRow.diamondCount; i++) {
	          this.imageList[i].personImage = zipObjIos.gifArr[i];
	        }
	        this.currentRow.switchover = zipObjIos.switchover; //展会切换图
	        this.currentRow.iosUrl = zipObjIos.iosUrl;
	        this.currentRow.androidUrl = zipObjAndroid.androidUrl;
	        edit_a_U3d = zipObjAndroid.zipPackage;
	        edit_i_U3d = zipObjIos.zipPackage;
	        this.unzipLoading = false;
		},
		//解压
	    unZip(iosFile) {
	      return new Promise(function (resolve, reject) {
	        let file = iosFile;
	        axios
	          .create()
	          .get(file, {
	            responseType: "arraybuffer"
	          })
	          .then(function (res) {
	            JSZip.loadAsync(res.data)
	              .then((content) => {
	                let bgArr = [];
	                let gifArr = [];
	                let androidUrl = "";
	                let iosUrl = "";
	                let switchover = "";
	                let zipObj = {
	                  bgArr: bgArr,
	                  gifArr: gifArr,
	                  androidUrl: androidUrl,
	                  iosUrl: iosUrl,
	                  switchover: switchover,
	                  zipPackage: content
	                };
	                let isBg = [];
	                let isGif = [];
	                console.log("解压文件", content.files);
	                for (let name in content.files) {
	                  let nameLength = name.length;
	                  let isImg = name.substring(nameLength - 3, nameLength); //png
	                  let isSwitchover = name.substring(15, 25);
	                  let blob = new Blob([content.files[name]._data.compressedContent]);
	                  if (isImg === "png" && isSwitchover !== "switchover") {
	                    isBg.push(content.files[name]);
	                  } else if (isImg === "gif") {
	                    isGif.push(content.files[name]);
	                  } else if (isImg === "u3d") {
	                    zipObj.androidUrl = URL.createObjectURL(blob);
	                    zipObj.iosUrl = URL.createObjectURL(blob);
	                  } else if (isSwitchover === "switchover") {
	                    zipObj.switchover = URL.createObjectURL(blob);
	                  } else {
	                  }
	                }
	
	                let arr1 = isBg.sort((a, b) => { //背景图替换后排序
	                  let x = a.name.substring(a.name.lastIndexOf("\/") + 1, a.name.length);
	                  let xx = x.substring(0, x.length - 4);
	                  let y = b.name.substring(b.name.lastIndexOf("\/") + 1, b.name.length);
	                  let yy = y.substring(0, y.length - 4);
	                  return xx - yy;
	                });
	                arr1.forEach(item => {
	                  let blob = new Blob([item._data.compressedContent]);
	                  zipObj.bgArr.push(URL.createObjectURL(blob));
	                });
	
	                let arr2 = isGif.sort((a, b) => { //人物图替换后排序
	                  let x = a.name.substring(a.name.lastIndexOf("\/") + 1, a.name.length);
	                  let xx = x.substring(0, x.length - 4);
	                  let y = b.name.substring(b.name.lastIndexOf("\/") + 1, b.name.length);
	                  let yy = y.substring(0, y.length - 4);
	                  return xx - yy;
	                });
	                arr2.forEach(item => {
	                  let blob = new Blob([item._data.compressedContent]);
	                  zipObj.gifArr.push(URL.createObjectURL(blob));
	                });
	
	                resolve(zipObj);
	              })
	              .catch((err) => {
	                console.log(err);
	              });
	          });
	      });
	    },
	}
}
</script>

完毕

下面说说难点
1、编辑时候,若更换了1张图片再压缩,则压缩包里面只显示这一张新上传的图片,因此需要做一份缓存,更换图片的时候,先删除在添加
2、编辑的时候,改换背景图或者人物图,更换的图片会在数组最后面,因此需要排序后再push

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值