碰到一个导入注册码的需求,用户可以将多个注册码打包成一个zip文件然后上传到服务器中,服务器会返回导入成功的注册码的数量。现在是前端需要在上传之前(之后也行)获取到用户上传的压缩包中的文件数量,第一次碰到前端操作zip压缩包的情况,在此记录一下,主要参考:
前端解析zip压缩包 --- vue、react等等通用_vue前端解析zip字节流图片-CSDN博客
我这里实现思路是在上传之前记录zip压缩包中的数量,然后在上传成功后与接口返回的数量作比较,部分代码如下:
<el-upload
ref="upload"
:before-upload="checkType"
accept=".zip"
class="upload-demo"
:on-success="uploadSuccess"
>
import JSZip from 'jszip'
checkType(file){
const fileName = file.name;
const fileType = fileName.substring(fileName.lastIndexOf('.'));
if(fileType !== '.zip'){
this.$message({
message: this.$t("请上传zip文件"),
type: "success"
});
return false;
}
const zip = new JSZip()
zip.loadAsync(file).then((zip) => {
this.count = Object.keys(zip.files).length;
})
return true
},
uploadSuccess(res) {
console.log("压缩包中文件个数: " + this.count);
if (res.code == 0 && res.data != null) {
if (res.data == this.count) {
this.$message({
message: "导入注册码成功!",
type: "success",
});}
else if (this.count > 1) {
this.$message({
message: `成功导入 ${res.data} 个注册码!`,
type: "success",
});
} else {
this.$message({
message: `导入注册码失败!`,
type: "error",
});
}
题外话:
另外我还找了一下前端操作其他格式的压缩包,比如7z, rar, tgz,发现并没有很完善的相关库支持,而且我看别的文章说解压缩这种比较耗CPU的尽量放到服务端。这次这个完全也是可以放到服务端的,不过既然需求是要前端改,那就没办法了。其实这里也还可以优化一下,限制zip压缩包里面的文件类型,还是可以参考前面那篇文章,我这里就不赘述了
很快啊,一更新上去测试就提出来说要对压缩包里面的文件类型做限制。我心想这不巧了吗,我之前参考的那片博客刚好可以用起来。然后就有了如下代码:
async checkType(file){
const fileName = file.name;
const fileType = fileName.substring(fileName.lastIndexOf('.'));
if(fileType !== '.zip'){
this.$message({
message: this.$t("请上传zip文件"),
type: "error"
});
return Promise.reject();
}
const zip = new JSZip()
let flag = true;
try {
const zipContent = await zip.loadAsync(file);
this.count = Object.keys(zipContent.files).length;
for (const key of Object.keys(zipContent.files)) {
console.log(zipContent.files[key].name);
if (!zipContent.files[key].name.endsWith('.i')) {
flag = false;
break;
}
}
} catch (error) {
this.$message({
message: this.$t("解压文件失败"),
type: "error"
});
return Promise.reject();
}
if (!flag) {
this.$message({
message: this.$t("导入注册码失败, 压缩包内包含非要求格式文件!"),
type: "error"
});
return Promise.reject();
}
return Promise.resolve();
},
这里面有一点我太理解的就是使用return false的时候,在检查压缩包文件名的是可以正常停止上传操作的,但是在处理压缩包里面的文件的时候就不生效了,即使通过debugger看到了提示内部文件不符合要求,但是还是会执行上传文件操作。然后又去瞄了一眼官方文档:
然后就试着改成Promise,就可以了。虽然问题是解决了,但是感觉自己对Promise还是理解的不是很到位。