我们Java 日常开发的时候。经常会遇到各种导除,例如导除word 、excel等。
今天我们了解下。导除zip 格式。我们使用poi 新生成的文件,和服务器中存的文件,怎么同时压缩到一个文件夹中。
通常情况,我们是以流的形式,直接输出到前台。那么我们在做压缩文件的时候,就不应该把流输出到前台,而是加入到压缩包的流。
项目框架使用的是若依框架。实际情况根据自身决定,本人前台知识也比较薄弱。
下面我们上代码:
工具类
package cf.ding.web.utils;
import cf.ding.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Slf4j
public class ZipUtils {
/**
* 设置返回前端文件名
* @param response response
* @param fileName 文件名,包含后缀
* @return OutputStream
* @throws Exception Exception
*/
public static OutputStream getOutputStreamFileName(HttpServletResponse response, String fileName) throws Exception {
response.reset();
String fileType = fileName.split("\\.")[1].toLowerCase();
switch (fileType){
case "doc":
response.setContentType("application/msword");//设置生成的文件类型
break;
case "docx":
response.setContentType("application/msword");//设置生成的文件类型
break;
case "xls":
response.setContentType("application/vnd.ms-excel");//设置生成的文件类型
break;
case "xlsx":
response.setContentType("application/vnd.ms-excel");//设置生成的文件类型
break;
case "pdf":
response.setContentType("application/pdf");//设置生成的文件类型
break;
case "zip":
response.setContentType("application/zip");//设置生成的文件类型
break;
case "dbf":
response.setContentType("application/x-dbf");//设置生成的文件类型
break;
default:
return response.getOutputStream();
}
response.setCharacterEncoding("UTF-8");//设置文件头编码方式和文件名
// response.setHeader("Content-Disposition", "attachment;filename=" +
// new String(URLEncoder.encode(fileName, "UTF-8").getBytes("utf-8"), "ISO8859-1"));
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName,"utf8")); //刷新缓冲
return response.getOutputStream();
}
/**
* 压缩文件
* @param response response
* @param filePath 文件路径
* @param fileName 压缩生成文件名
* @throws IOException IOException
*/
public static void zipDateFile(HttpServletResponse response, String filePath, String fileName) throws Exception {
if (StringUtils.isEmpty(filePath) || !new File(filePath).exists()) return;
List<File> allFile = getAllFile(filePath);
zipDateFile(response, getAllFile(filePath), fileName, true);
}
/**
* 压缩文件
* @param response response
* @param fileList 文件集合
* @param fileName 压缩生成文件名
* @throws IOException IOException
*/
public static void zipDateFile(HttpServletResponse response, List<File> fileList, String fileName, boolean deleteSourceFile) throws Exception {
getOutputStreamFileName(response, fileName);
ServletOutputStream servletOutputStream = response.getOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(servletOutputStream);
zipFile(fileList, zipOutputStream, true);
try {
zipOutputStream.close();
} catch (IOException e) {
log.error("流关闭失败", e);
}
}
/**
* 压缩导出
* @param fileList 文件列表
* @param zipOutputStream zip流
* @throws IOException IOException
*/
public static void zipFile(List<File> fileList, ZipOutputStream zipOutputStream, boolean deleteSourceFile) throws IOException {
byte[] buffer = new byte[1024];
for (File file : fileList) {
if (file.exists()) {
if (file.isFile()) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
int size = 0;
while ((size = bis.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, size);
}
zipOutputStream.closeEntry();
} finally {
if(deleteSourceFile) file.delete();
}
} else {
File[] files = file.listFiles();
if(null == files) continue;
List<File> childrenFileList = Arrays.asList(files);
zipFile(childrenFileList, zipOutputStream, deleteSourceFile);
}
}
}
}
/**
* 获取指定文件夹下所有文件,不含文件夹里的文件
* @param filePath 文件路径
* @return fileList
*/
public static List<File> getAllFile(String filePath) {
if (StringUtils.isEmpty(filePath)) return null;
return getAllFile(new File(filePath));
}
/**
* 获取指定文件夹下所有文件,不含文件夹里的文件
* @param dirFile 文件夹
* @return fileList
*/
public static List<File> getAllFile(File dirFile) {
// 如果文件夹不存在或着不是文件夹,则返回 null
if (Objects.isNull(dirFile) || !dirFile.exists() || dirFile.isFile()){
return null;
}
File[] childrenFiles = dirFile.listFiles();
if (Objects.isNull(childrenFiles) || childrenFiles.length == 0){
return null;
}
List<File> files = new ArrayList<>();
for (File childFile : childrenFiles) {
// 如果是文件,直接添加到结果集合
if (childFile.isFile()) {
files.add(childFile);
}
//以下几行代码取消注释后可以将所有子文件夹里的文件也获取到列表里
// else {
// // 如果是文件夹,则将其内部文件添加进结果集合
// List<File> cFiles = getAllFile(childFile);
// if (Objects.isNull(cFiles) || cFiles.isEmpty()) continue;
// files.addAll(cFiles);
// }
}
return files;
}
public static boolean createFilePath(String path){
try {
File filePath = new File(path);
if (!filePath.exists()) {
if(!filePath.mkdirs()){
return false;
}
}
} catch (Exception e) {
log.error("服务端创建文件夹出错",e);
return false;
}
return true;
}
public static boolean deleteFilePath(File file) {
if (file.isDirectory()) {
String[] children = file.list();
if(null != children && children.length > 0){
File file1 = null;
//递归删除目录中的子目录下
for(String str : children){
file1 = new File(file, str);
log.info(file1.getPath());
deleteFilePath(file1);
}
}
}
return file.delete();
}
public static void zipCompressFolder(HttpServletResponse response, String sourceFolder, String folderName, String fileName) throws Exception {
getOutputStreamFileName(response, fileName);
ServletOutputStream servletOutputStream = response.getOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(servletOutputStream);
compressFolder(sourceFolder, folderName, zipOutputStream);
// 新生成一个excel 然后加入压缩包
Map<String, Object> map = getTestMap();
exportExcelTax(folderName, map, zipOutputStream);
try {
zipOutputStream.close();
} catch (IOException e) {
log.error("流关闭失败", e);
}
}
private static Map<String, Object> getTestMap() {
Map<String, Object> map = new HashMap<>();
map.put("taxtype", "0");
map.put("name", "name");
map.put("taxNumber", "taxNumber");
map.put("address", "address");
map.put("tel", "tel");
map.put("bankName", "bankName");
map.put("bankNumber", "bankNumber");
return map;
}
/**
* 多文件,多文件夹 压缩
*
* @param response
* @param sourceFolders
* @param folderName
* @param fileName
* @param path 附件存储位置 前缀
* @param map 竞价明细
* @throws Exception
*/
public static void zipCompressMapFolder(HttpServletResponse response, Map<String, List<String>> sourceFolders,
Map<String, String> folderName, String fileName, String path, Map<String, Object> map) throws Exception {
getOutputStreamFileName(response, fileName);
ServletOutputStream servletOutputStream = response.getOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(servletOutputStream);
// 报名资料 和保证金资料
String[] ming = {"报名资料/", "保证金资料/"};
// todo 多文件逻辑处
try {
zipOutputStream.close();
} catch (IOException e) {
log.error("流关闭失败", e);
}
}
/**
* 压缩文件夹
* @param sourceFolder
* @param folderName
* @param zipOutputStream
* @throws IOException
*/
private static void compressFolder(String sourceFolder, String folderName, ZipOutputStream zipOutputStream) throws IOException {
File folder = new File(sourceFolder);
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
// 压缩子文件夹
compressFolder(file.getAbsolutePath(), folderName + "/" + file.getName(), zipOutputStream);
} else {
// 压缩文件
addToZipFile(folderName + "/" + file.getName(), file.getAbsolutePath(), zipOutputStream);
}
}
}
}
/**
* 多文件,多文件夹 压缩
* @param sourceFolders 存有 文件的文件夹
* @param folderName
* @param zipOutputStream
* @throws IOException
*/
private static void compressListFolder(List<String> sourceFolders, String folderName, ZipOutputStream zipOutputStream) throws IOException {
for (String sourceFolder : sourceFolders) {
File folder = new File(sourceFolder);
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
// 压缩子文件夹
compressFolder(file.getAbsolutePath(), folderName + "/" + file.getName(), zipOutputStream);
} else {
// 压缩文件
addToZipFile(folderName + "/" + file.getName(), file.getAbsolutePath(), zipOutputStream);
}
}
}
}
}
/**
* 路径方式加入 压缩包
* @param fileName
* @param fileAbsolutePath
* @param zipOutputStream
* @throws IOException
*/
private static void addToZipFile(String fileName, String fileAbsolutePath, ZipOutputStream zipOutputStream) throws IOException {
// 创建ZipEntry对象并设置文件名
ZipEntry entry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(entry);
// 读取文件内容并写入Zip文件
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(fileAbsolutePath);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, bytesRead);
}
// 完成当前文件的压缩
zipOutputStream.closeEntry();
} catch (IOException e) {
e.printStackTrace();
} finally {
fileInputStream.close();
}
}
/**
* BufferedInputStream 压缩到zip 中
* @param fileName
* @param fileInputStream
* @param zipOutputStream
* @throws IOException
*/
private static void addToZipFileBufferedInputStream(String fileName, BufferedInputStream fileInputStream, ZipOutputStream zipOutputStream) throws IOException {
// 创建ZipEntry对象并设置文件名
ZipEntry entry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(entry);
// 读取文件内容并写入Zip文件
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, bytesRead);
}
fileInputStream.close();
// 完成当前文件的压缩
zipOutputStream.closeEntry();
}
/**
* 发票信息采集单
* @param map
* @param zipOutputStream
*/
public static void exportExcelTax(String folderName, Map<String, Object> map, ZipOutputStream zipOutputStream) {
try {
if (map == null) {
throw new ServiceException("税务信息为空!");
}
// 声明一个工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
// sheet 页名称
HSSFSheet sheet = workbook.createSheet("发票信息采集单");
sheet.setMargin(HSSFSheet.LeftMargin,( double ) 10 );
sheet.setMargin(HSSFSheet.RightMargin,( double ) 10 );
sheet.setColumnWidth((short) 0, (short) 7000);// 设置列宽
sheet.setColumnWidth((short) 1, (short) 9000);// 设置列宽
sheet.setColumnWidth((short) 2, (short) 12000);// 设置列宽
// sheet.setColumnWidth((short) 3, (short) 4500);// 设置列宽
HSSFCellStyle cellstyle = workbook.createCellStyle();
cellstyle.setBorderBottom(BorderStyle.THIN);//下边框
cellstyle.setBorderLeft(BorderStyle.THIN);//左边框
cellstyle.setBorderTop(BorderStyle.THIN);//上边框
cellstyle.setBorderRight(BorderStyle.THIN);//右边框
cellstyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
cellstyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
HSSFFont font3 = workbook.createFont();
font3.setFontName("宋体");
font3.setFontHeightInPoints((short) 15);
cellstyle.setFont(font3);
HSSFCellStyle cellstyle2 = workbook.createCellStyle();
cellstyle2.setBorderBottom(BorderStyle.THIN);//下边框
cellstyle2.setBorderLeft(BorderStyle.THIN);//左边框
cellstyle2.setBorderTop(BorderStyle.THIN);//上边框
cellstyle2.setBorderRight(BorderStyle.THIN);//右边框
cellstyle2.setAlignment(HorizontalAlignment.CENTER);//水平居中
cellstyle2.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
HSSFFont font2 = workbook.createFont();
font2.setFontName("方正仿宋简体");
font2.setFontHeightInPoints((short) 12);
cellstyle2.setFont(font2);
HSSFRow row0 = sheet.createRow(0);
row0.setHeight((short) (40*20));
int k = 3;
HSSFCell cell10 = row0.createCell(0);
for (int i1 = 0; i1 < k; i1++) {
cell10 = row0.createCell(i1);
if (i1 == 0) {
cell10.setCellValue("发票信息采集单");
}
cell10.setCellStyle(cellstyle);
}
// 合并第一行单元格
CellRangeAddress region = new CellRangeAddress(0,0,0,2);
sheet.addMergedRegion(region);
HSSFRow row1 = sheet.createRow(1);
HSSFCell cell1_0 = row1.createCell(0);
cell1_0.setCellValue("发票类型及提供信息要求");
cell1_0.setCellStyle(cellstyle2);
HSSFCell cell1_1 = row1.createCell(1);
cell1_1.setCellValue("增值税普通发票");
cell1_1.setCellStyle(cellstyle2);
HSSFCell cell1_2 = row1.createCell(2);
Integer taxtype = (Integer)map.get("taxtype");
String pttypeStr = "是";
String zytypeStr = "是";
if (taxtype == 0) {
zytypeStr = "否";
} else {
pttypeStr = "否";
}
cell1_2.setCellValue(pttypeStr);
cell1_2.setCellStyle(cellstyle2);
HSSFRow row2 = sheet.createRow(2);
HSSFCell cell2_0 = row2.createCell(0);
cell2_0.setCellValue("");
cell2_0.setCellStyle(cellstyle2);
HSSFCell cell2_1 = row2.createCell(1);
cell2_1.setCellValue("增值税专用发票");
cell2_1.setCellStyle(cellstyle2);
HSSFCell cell2_2 = row2.createCell(2);
cell2_2.setCellValue(zytypeStr);
cell2_2.setCellStyle(cellstyle2);
HSSFRow row3 = sheet.createRow(3);
HSSFCell cell3_0 = row3.createCell(0);
cell3_0.setCellValue("");
cell3_0.setCellStyle(cellstyle2);
HSSFCell cell3_1 = row3.createCell(1);
cell3_1.setCellValue("发票单位名称");
cell3_1.setCellStyle(cellstyle2);
HSSFCell cell3_2 = row3.createCell(2);
cell3_2.setCellValue((String) map.get("name"));
cell3_2.setCellStyle(cellstyle2);
HSSFRow row4 = sheet.createRow(4);
HSSFCell cell4_0 = row4.createCell(0);
cell4_0.setCellValue("");
cell4_0.setCellStyle(cellstyle2);
HSSFCell cell4_1 = row4.createCell(1);
cell4_1.setCellValue("纳税人识别号");
cell4_1.setCellStyle(cellstyle2);
HSSFCell cell4_2 = row4.createCell(2);
cell4_2.setCellValue((String) map.get("taxNumber"));
cell4_2.setCellStyle(cellstyle2);
HSSFRow row5 = sheet.createRow(5);
HSSFCell cell5_0 = row5.createCell(0);
cell5_0.setCellValue("");
cell5_0.setCellStyle(cellstyle2);
HSSFCell cell5_1 = row5.createCell(1);
cell5_1.setCellValue("开票单位地址、电话");
cell5_1.setCellStyle(cellstyle2);
HSSFCell cell5_2 = row5.createCell(2);
cell5_2.setCellValue(map.get("address")+" "+map.get("tel"));
cell5_2.setCellStyle(cellstyle2);
HSSFRow row6 = sheet.createRow(6);
HSSFCell cell6_0 = row6.createCell(0);
cell6_0.setCellValue("");
cell6_0.setCellStyle(cellstyle2);
HSSFCell cell6_1 = row6.createCell(1);
cell6_1.setCellValue("开票单位开户行及帐号");
cell6_1.setCellStyle(cellstyle2);
HSSFCell cell6_2 = row6.createCell(2);
cell6_2.setCellValue(map.get("bankName")+" "+map.get("bankNumber"));
cell6_2.setCellStyle(cellstyle2);
HSSFRow row7 = sheet.createRow(7);
HSSFCell row7_0 = row7.createCell(0);
row7_0.setCellValue("");
row7_0.setCellStyle(cellstyle2);
HSSFCell cell7_1 = row7.createCell(1);
cell7_1.setCellValue("货物或应税服务名称");
cell7_1.setCellStyle(cellstyle2);
HSSFCell cell7_2 = row7.createCell(2);
cell7_2.setCellValue("交易服务费");
cell7_2.setCellStyle(cellstyle2);
HSSFRow row8 = sheet.createRow(8);
HSSFCell row8_0 = row8.createCell(0);
row8_0.setCellValue("");
row8_0.setCellStyle(cellstyle2);
HSSFCell cell8_1 = row8.createCell(1);
cell8_1.setCellValue("备注栏内容");
cell8_1.setCellStyle(cellstyle2);
HSSFCell cell8_2 = row8.createCell(2);
cell8_2.setCellValue("时代开具");
cell8_2.setCellStyle(cellstyle2);
CellRangeAddress regionl = new CellRangeAddress(1,8,0,0);
sheet.addMergedRegion(regionl);
ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
workbook.write(fileOut);
// 4、输出流转换成输入流
byte[] content = fileOut.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(content);
BufferedInputStream in = new BufferedInputStream(is);
addToZipFileBufferedInputStream(folderName+"/发票信息采集单.xlsx", in, zipOutputStream);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
导出 word 同理,主要是 调用
exportExcelTax(String folderName, Map<String, Object> map, ZipOutputStream zipOutputStream) 方法
结尾的 6 句代码
ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
workbook.write(fileOut);
// 4、输出流转换成输入流
byte[] content = fileOut.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(content);
BufferedInputStream in = new BufferedInputStream(is);
addToZipFileBufferedInputStream(folderName+"/发票信息采集单.xlsx", in, zipOutputStream);
注意 同一个 压缩包 必须使用同一个压缩流 zipOutputStream
下面简单粘贴下。前台后台代码。
vue 添加按钮 添加点击事件
注意:方法中 必须要加 responseType:‘blob’
后台方法
导出效果如下:
导出excel 效果
poi 用的是 wps
org.apache.poi poi-ooxml 4.1.2