前端压缩

基于JSZip的前端文件压缩

1. 简介:

这段时间,项目需要做一个这样的功能:客户端在上传文件的时候(具体文件类型),需要对文件进行压缩再上传以节省带宽和服务器端资源,完成这个功能,我们选择了GitHub上的JSZip,它是一个客户端插件,可以提供客户端压缩功能,作者给出了API,但是实际使用过程中还是有很多问题,下面是实际过程中遇到的各类问题,直至最终完成整个文件压缩再上传至后台。

2.项目相关组件与环境:

前端node.js + webpack 作前后台分离,后端java

3. 具体实现

主要js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var JSZip = require('jszip');
const components = require('components');

$('#confirmBtn').on('click', async function() {
// 绑定上传的确认按钮,获取到obj等模型文件,并压缩
let zip = new JSZip();//声明并创建JSZip对象
var fileBox = $('#fileUploadInput'); //从页面获取到需要上传的文件列表,当然html是一个多文件上传
var fileList = fileBox[0].files;
var objName = 'example'; // 这里定义一个压缩文件的名字,以供后台使用,当然也可以动态获取
// var flag = false;
for (const fileObject of fileList) {
zip = await zipFileAsync(zip, fileObject); //这是设置异步上传,await关键字使得后面的zipFileAsync方法执行结束后才将对象返回给zip变量
}
sendFileAsync(zip, objName);
console.log(zip);
return false; // 设置return false防止表单提交
});

这部分代码就是异步压缩的核心,以及如何调用的下面的异步压缩算法,上面需要Async与await关键字缺一不可,一开始也尝试过使用同步压缩的方式,但是会出现压缩还没有全部完成,就已经开始提交文件的现象,特别感谢lrh3321的指导,才完整的实现了这个功能。


因为异步压缩的时候我们上传的文件的数量不定,所以上面需要使用await关键字来修饰压缩过程。而下面的压缩过程的实现,最终返回一个promise对象,当压缩过程已完成后,完整的生成的文件存于其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 异步压缩文件
* @param zip file
*/
function zipFileAsync(zip, file) {
const promise = new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function(e) {
var result = reader.result;
// 读完转一下格式
result = convertBase64UrlToBlob(result);
console.log(zip);
console.log(file.name);
console.log(file.size);
// resolve 方法保证异步压缩完成后才返回promise
resolve(
zip.file(file.name, result, {
type: 'blob',
}));
};
});
return promise;
}


这里的demo请查看JSZip给的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 异步发送文件
* @param zip file
*/
function sendFileAsync(zip, objName) {
zip.generateAsync({
type: 'blob',
compression: 'DEFLATE', // force a compression for this file
compressionOptions: { // 使用压缩等级,1-9级,1级压缩比最低,9级压缩比最高
level: 6,
},
}).then(
function(content) {
var formData = new FormData();
formData.append('Blobfile', content); // 获取上文中压缩的内容,并放入formdata
formData.append('objName', objName); // 将objName一起放入formdata
progressBar('Model/UploadModel', formData, content.size);
}
);
return false;
}
/**
* 将以base64的图片url数据转换为Blob
* @param urlData
* 用url方式表示的base64图片数据
*/

http读取图片的时候会已base64编码形式对到服务器,如果不进行重新编码,则无法在图片查看器中查看图片

1
2
3
4
5
6
7
8
9
10
function convertBase64UrlToBlob(urlData) {
var bytes = window.atob(urlData.split(',')[1]);
// 处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {type: 'image/jpg'});
}
Donate comment here