最近碰到个需要下载zip压缩包的需求,于是我在网上找了下别人写好的zip工具类。但找了好多篇博客,总是发现有bug。因此就自己来写了个工具类。
这个工具类的功能为:
- (1)可以压缩文件,也可以压缩文件夹
- (5)代码中提供了2个压缩文件的方法,一个的输入参数为文件夹路径,一个为文件列表,可根据实际需求选择方法。
- (4)可以选择是否保留原来的目录结构,如果不保留,所有文件跑压缩包根目录去了,且空文件夹直接舍弃。注意:如果不保留文件原来目录结构,在碰到文件名相同的文件时,会压缩失败。
- (3)碰到空的文件夹,也可以压缩
- (2)同时支持压缩多级文件夹,工具内部做了递归处理
20200919补充导出excel xlsx vue-filesaver代码
一、saveAs语法
saveAs()从文件保存器导入
import { saveAs } from 'file-saver';
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })
传递{ autoBom: true }如果你想FileSaver.js自动提供Unicode文本编码提示(:见字节顺序标记)。请注意,只有在您的Blob类型已charset=utf-8设置的情况下才能执行此操作。
--------#系统导出excel post export function postExport(url,data = {}){ console.log("postExport",url,data); return new Promise((resolve,reject) => { axios.post(url,data,{ responseType:'blob' }).then(response => { let blob = new Blob([response.data], { type: "application/vnd.ms-excel" }); FileSaver.saveAs(blob, "export.xlsx"); }
本来想封装一个class,用于导出excel,图片,zip;无意间发现这老哥已经做了这件事,那就贴出来,不造轮子了
链到:https://blog.csdn.net/qq_30671099/article/details/104052782 #主要代码如下
import FileSaver from "file-saver";
export default class fileSave {
/**
* 导出Excel文件
* @param {*} res 文件流
* @param {*} name 文件名
*/
static getExcel(res, name) {
let blob = new Blob([res], {
type: "application/vnd.ms-excel"
});
FileSaver.saveAs(blob, name + ".xlsx");
}
/**
* 导出CSV文件
* @param {*} res 文件流
* @param {*} name 文件名
*/
static getCsv(res, name) {
let blob = new Blob([res], {
type: "application/vnd.ms-excel"
});
FileSaver.saveAs(blob, name + ".csv");
}
/**
* 导出图片1
* @param {*} url 图片地址
* @param {*} name 文件名
*/
static getImgURLs(url, name) {
let last = url.substring(url.lastIndexOf("."), url.length);
FileSaver.saveAs(url, `${name}${last}`);
}
/**
* 导出图片2
* @param {*} res 文件流
* @param {*} name 文件名
*/
static downLoadImg(res, filename) {
let blob = new Blob([res], {
type: "image/jpeg"
});
FileSaver.saveAs(blob, `${filename}.jpg`);
}
}
使用:
1.导入
import exportFile from '@/utils/exportFile'
2.使用
exportFile.getExcel(res.data, '近年走势')
20200514 : 导出zip
下面直接上代码
/**
* 1: 读取ots的过程数据 写成excel文件到临时文件夹内
*/
List<DownloadOtsData> listOtsData001= new ArrayList<DownloadOtsData>(10);
for (int i = 0; i < 10; i++) {
DownloadOtsData data = new DownloadOtsData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56+i);
listOtsData001.add(data);
}
/**
* 2: 读取ots的过程数据2 写成excel文件到临时文件夹内
*/
List<DownloadOtsData> listOtsData002 = new ArrayList<DownloadOtsData>(100);
for (int i = 0; i < 100; i++) {
DownloadOtsData data = new DownloadOtsData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56+i);
listOtsData002.add(data);
}
/** 3.创建临时文件夹 */
String rootPath = request.getSession().getServletContext().getRealPath("/");
System.out.println("---临时文件夹路径:---"+rootPath);
String zipDir=rootPath + "/" + "testNo实验编号";
System.out.println("---创建此实验编号临时文件夹---"+zipDir);
File temDir = new File(zipDir);
if(!temDir.exists()){
temDir.mkdirs();
}
// 写listOtsData001到临时文件夹下
String fileName = zipDir+"\\" + System.currentTimeMillis() + "listOtsData001.xlsx";
EasyExcel.write(fileName, DownloadOtsData.class).sheet("sheet1").doWrite(listOtsData001);
// 写listOtsData002到临时文件夹下
String listOtsData001Name = zipDir+"\\" + System.currentTimeMillis() + "listOtsData002.xlsx";
EasyExcel.write(listOtsData001Name, DownloadOtsData.class).sheet("sheet1").doWrite(listOtsData002);
try {
/** 4.1 调用工具类,压缩临时实验的压缩包
* 4.2设置response的header(注意4.1/4.2顺序)
* */
ZipUtils.toZip(temDir.getPath(), response.getOutputStream(),true);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=testNo.zip");
/** 5.删除临时文件夹:这里我们不需要保留目录结构, 这里我没写递归,直接就这样删除了 */
File[] listFiles = temDir.listFiles();
for (int i = 0; i < listFiles.length; i++) {
listFiles[i].delete();
}
temDir.delete();
} catch (IOException e) {
e.printStackTrace();
res=-1;
}
vue前端下载
export function hget(url,params={}){
return new Promise((resolve,reject) => {
axios.get(url,{
params:params,
responseType:'blob'
},)
.then(response => {
let data = response.data;
let fileReader = new FileReader();
fileReader.onload = function() {
try {
let jsonData = JSON.parse(this.result); // 说明是普通对象数据,后台转换失败
if (jsonData.code) {
that.$message.error(jsonData.message)
}
} catch (err) { // 解析成对象失败,说明是正常的文件流
const blob = new Blob([response.data], {type: 'application/zip'});
const filename = response.headers['content-disposition'];
console.log(filename);
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob); //创建下载的链接
downloadElement.href = href;
[downloadElement.download] = ['download-'+new Date().toLocaleDateString()];
document.body.appendChild(downloadElement);
downloadElement.click(); //点击下载
document.body.removeChild(downloadElement); //下载完成移除元素
window.URL.revokeObjectURL(href); //释放blob对
}
};
fileReader.readAsText(data)
})
.catch(err => {
reject(err)
})
})
}
结果:
二、注意事项
写该工具类时,有些注意事项说一下:
(1)支持选择是否保留原来的文件目录结构,如果不保留,那么空文件夹直接不用处理。
(1)碰到空文件夹时,如果需要保留目录结构,则直接添加个ZipEntry就可以了,不过就是这个entry的名字后面需要带上一斜杠(/)表示这个是目录。
(2)递归时,不需要把zip输出流关闭,zip输出流的关闭应该是在调用完递归方法后面关闭
(3)递归时,如果是个文件夹且需要保留目录结构,那么在调用方法压缩他的子文件时,需要把文件夹的名字加一斜杠给添加到子文件名字前面,这样压缩后才有多级目录。
三、如何在javaWeb项目中使用该工具类
这个工具类在web项目中的使用场景就是多文件下载,我就简单说个下载多个excel表格的案例吧。
代码中的步骤为:
(1)创建一个临时文件夹
(2)将要下载的文件生成至该临时文件夹内
(3)当所有文件生成完后,获取HttpServletResponse获取设置下载的header
(4)调用工具类的方法,传入上面生成的临时文件夹路径及response获取的输出流;这样就下载出来zip包了
(5)递归删除掉上面生成的临时文件夹和文件
参考:https://www.cnblogs.com/baifubin/p/12335089.html
https://www.cnblogs.com/zeng1994/p/7862288.html