import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@SuppressWarnings("restriction")
public class FileDownloadUtils {
private static final Logger logger = LoggerFactory.getLogger(FileDownloadUtils.class);
/\*\*
\* 编译下载的文件名
\* @param filename
\* @param agent
\* @return
\* @throws IOException
\*/
public static String encodeDownloadFilename(String filename, String agent)throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
+ "?=";
filename = filename.replaceAll("\r\n", "");
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+"," ");
}
return filename;
}
/\*\*
\* 创建文件夹;
\* @param path
\*/
public static void createFile(String path) {
File file = new File(path);
//判断文件是否存在;
if (!file.exists()) {
//创建文件;
file.mkdirs();
}
}
/\*\*
\* 生成.zip文件;
\* @param path
\* @throws IOException
\*/
public static ZipOutputStream craeteZipPath(String path) throws IOException{
ZipOutputStream zipOutputStream = null;
File file = new File(path+DateUtils.getDateWx()+".zip");
zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
File[] files = new File(path).listFiles();
FileInputStream fileInputStream = null;
byte[] buf = new byte[1024];
int len = 0;
if(files!=null && files.length > 0){
for(File excelFile:files){
String fileName = excelFile.getName();
fileInputStream = new FileInputStream(excelFile);
//放入压缩zip包中;
zipOutputStream.putNextEntry(new ZipEntry(path + "/"+fileName));
//读取文件;
while((len=fileInputStream.read(buf)) >0){
zipOutputStream.write(buf, 0, len);
}
//关闭;
zipOutputStream.closeEntry();
if(fileInputStream != null){
fileInputStream.close();
}
}
}
/\*if(zipOutputStream !=null){
zipOutputStream.close();
}\*/
return zipOutputStream;
}
/\*\*
\* //压缩文件
\* @param srcfile 要压缩的文件数组
\* @param zipfile 生成的zip文件对象
\*/
public static void ZipFiles(java.io.File[] srcfile, File zipfile) throws Exception {
byte[] buf = new byte[1024];
FileOutputStream fos = new FileOutputStream(zipfile);
ZipOutputStream out = new ZipOutputStream(fos);
for (int i = 0; i < srcfile.length; i++) {
FileInputStream in = new FileInputStream(srcfile[i]);
out.putNextEntry(new ZipEntry(srcfile[i].getName()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
}
out.close();
fos.flush();
fos.close();
}
/\*\*
\* 删除文件夹及文件夹下所有文件
\* @param dir
\* @return
\*/
public static boolean deleteDir(File dir) {
if (dir == null || !dir.exists()){
return true;
}
if (dir.isDirectory()) {
String[] children = dir.list();
//递归删除目录中的子目录下
for (int i=0; i<children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}
/\*\*
\* 生成html
\* @param msg
\* @return
\* @author zgd
\* @time 2018年6月25日11:47:07
\*/
public static String getErrorHtml(String msg) {
StringBuffer sb = new StringBuffer();
sb.append("<html>");
sb.append("<head>");
sb.append("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>");
sb.append("</head>");
sb.append("<body>");
sb.append("<div id='errorInfo'> ");
sb.append("</div>");
sb.append("<script>alert('"+msg+"')</script>");
sb.append("</body>");
sb.append("</html>");
return sb.toString();
}
/\*\*
\* 设置下载excel的响应头信息
\* @param response
\* @param request
\* @param agent
\* @param fileName
\* @throws IOException
\* @author zgd
\* @time 2018年6月25日11:47:07
\*/
public static void setExcelHeadInfo(HttpServletResponse response, HttpServletRequest request, String fileName) {
try {
// 获取客户端浏览器的类型
String agent = request.getHeader("User-Agent");
// 对文件名重新编码
String encodingFileName = FileDownloadUtils.encodeDownloadFilename(fileName, agent);
// 告诉客户端允许断点续传多线程连接下载
response.setHeader("Accept-Ranges", "bytes");
//文件后缀
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + encodingFileName);
} catch (IOException e) {
logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() +"发生的异常是: ",e);
throw new RuntimeException(e);
}
}
/\*\*
\* 设置下载zip的响应头信息
\* @param response
\* @param fileName 文件名
\* @param request
\* @throws IOException
\* @author zgd
\* @time 2018年6月25日11:47:07
\*/
public static void setZipDownLoadHeadInfo(HttpServletResponse response, HttpServletRequest request, String fileName) throws IOException {
// 获取客户端浏览器的类型
String agent = request.getHeader("User-Agent");
response.setContentType("application/octet-stream ");
// 表示不能用浏览器直接打开
response.setHeader("Connection", "close");
// 告诉客户端允许断点续传多线程连接下载
response.setHeader("Accept-Ranges", "bytes");
// 对文件名重新编码
String encodingFileName = FileDownloadUtils.encodeDownloadFilename(fileName, agent);
response.setHeader("Content-Disposition", "attachment; filename=" + encodingFileName);
}
}
1.控制层接收参数
/\*\*
\* 导出商家订单数据列表的excel文件
\*
\* @param request
\* @author zgd
\* @time 2018年6月5日14:47:21
\*/
@RequestMapping(value = "/exportStoreOrderList")
public void exportStoreOrderList(HttpServletRequest request, HttpServletResponse response) {
/\*
\* 从service层获取List的数据,此处省略
\*/
List<Map<String, Object>> list = data;
//导出excel
// 创建Excel文件,每个excel限制10000条数据,超过则打包zip
int size = 10000;
//每次缓存1000条到内存,其余写到磁盘
int rowCache = 1000;
String fileName = "商家订单数据-" + DateUtils.getDateWx();
// 创建Excel文件,每个excel限制10000条数据,超过则打包zip
int size = 10000;
//每次缓存1000条到内存,其余写到磁盘
int rowCache = 1000;
String fileName = "商家订单数据-" + DateUtils.getDateWx();
//导出excel
try {
//excel文件个数
int n = list.size() / size + 1;
if (list != null) {
SXSSFWorkbook workbook = getStoreOrderExcel(list, rowCache);
if (n == 1) {
//下载单个excle
fileName = fileName + ".xls";
FileDownloadUtils.downloadExcel(request, response, fileName, workbook);
} else {
fileName = "批量" + fileName + ".zip";
String realPath = request.getSession().getServletContext().getRealPath("WEB-INF");
//创建临时文件夹保存excel
String tempDir = realPath + "/tempDir/" + DateUtils.getDateWx();
List<File> files = getStoreOrderExcels(tempDir, size, list, rowCache);
String zipPath = tempDir + "\\" + fileName;
//下载zip
FileDownloadUtils.downloadZip(request, response, fileName, files, zipPath);
//删除tempDir文件夹和其中的excel和zip文件
boolean b = FileDownloadUtils.deleteDir(new File(realPath + "\\tempDir"));
if (!b) {
throw new RuntimeException("tempDir文件夹及其中的临时Excel和zip文件删除失败");
}
}
}
}catch (Exception e) {
try {
if (!response.isCommitted()) {
response.setContentType("text/html;charset=utf-8");
response.setHeader("Content-Disposition", "");
String html = FileDownloadUtils.getErrorHtml("下载失败");
response.getOutputStream().write(html.getBytes("UTF-8"));
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
2. getStoreOrderExcel方法解析
/\*\*
\* 将数据库查出来的商家订单数据,创建成excel
\* @param list 商家订单数据
\* @param rowCache 缓冲的行数
\* @return
\*/
private SXSSFWorkbook getStoreOrderExcel(List<Map<String, Object>> list, int rowCache) {
//如果rowCache是1000,就是每次读取1000条数据到缓存中
SXSSFWorkbook workbook = new SXSSFWorkbook(rowCache);
/\*\*
....设置行,列,塞入数据
\*\*/
return workbook;
}
2.1 这里分成两条线: 下载excel和下载zip
2.2 下载excel支线
2.2.1 downloadExcel方法解析
/\*\*
\* 下载excel
\*
\* @param request
\* @param response
\* @param fileName
\* @param workbook
\* @throws Exception
\* @author zgd
\* @time 2018年6月25日11:47:07
\*/
private void downloadExcel(HttpServletRequest request, HttpServletResponse response, String fileName, SXSSFWorkbook workbook) {
//一个流两个头
//设置下载excel的头信息
FileDownloadUtils.setExcelHeadInfo(response, request, fileName);
// 写出文件
ServletOutputStream os = null;
try {
os = response.getOutputStream();
workbook.write(os);
} catch (IOException e) {
logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + "发生的异常是: ", e);
throw new RuntimeException(e);
} finally {
try {
if (os != null) {
os.flush();
![img](https://img-blog.csdnimg.cn/img_convert/3aeb752d1a3b307520e6f168816449c5.png)
![img](https://img-blog.csdnimg.cn/img_convert/fa6792eab841799dc9f9ba8095f05ccd.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
os.flush();
[外链图片转存中...(img-A9CBmWCp-1714704140903)]
[外链图片转存中...(img-7yhtOP89-1714704140903)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**