Java實(shí)現(xiàn)一次性下載多個(gè)文件
最近項(xiàng)目遇到一個(gè)需求,需要一次性導(dǎo)出全部數(shù)據(jù),而且是按照500條數(shù)據(jù)一個(gè)文件。
話不多說,開始。
新增Excel工具類
可以直接復(fù)制
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
//關(guān)于下面這兩個(gè)包,可以直接用Java自帶的,也可以導(dǎo)入
//我這里是導(dǎo)入的,可以進(jìn)行一個(gè)編碼的設(shè)置,不過我是沒有設(shè)置成功,反而亂碼
//建議里面的文件名什么的都用英文,不用擔(dān)心亂碼,哈哈
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ExportExcel {
// 顯示的導(dǎo)出表的標(biāo)題
private String title;
// 導(dǎo)出表的列名
private String[] rowName;
private List<Object[]> dataList = new ArrayList<Object[]>();
public ExportExcel() {
}
// 構(gòu)造函數(shù),傳入要導(dǎo)出的數(shù)據(jù)
public ExportExcel(String title, String[] rowName, List<Object[]> dataList) {
this.dataList = dataList;
this.rowName = rowName;
this.title = title;
}
// 導(dǎo)出數(shù)據(jù)
public void export(OutputStream out) throws Exception {
try {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet(title);
// 產(chǎn)生表格標(biāo)題行
HSSFRow rowm = sheet.createRow(0);
HSSFCell cellTitle = rowm.createCell(0);
//sheet樣式定義【】
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
HSSFCellStyle style = this.getStyle(workbook);
sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
cellTitle.setCellStyle(columnTopStyle);
cellTitle.setCellValue(title);
// 定義所需列數(shù)
int columnNum = rowName.length;
HSSFRow rowRowName = sheet.createRow(2);
// 將列頭設(shè)置到sheet的單元格中
for (int n = 0; n < columnNum; n++) {
HSSFCell cellRowName = rowRowName.createCell(n);
cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
cellRowName.setCellValue(text);
cellRowName.setCellStyle(columnTopStyle);
}
// 將查詢到的數(shù)據(jù)設(shè)置到sheet對(duì)應(yīng)的單元格中
for (int i = 0; i < dataList.size(); i++) {
Object[] obj = dataList.get(i);// 遍歷每個(gè)對(duì)象
HSSFRow row = sheet.createRow(i + 3);// 創(chuàng)建所需的行數(shù)
for (int j = 0; j < obj.length; j++) {
HSSFCell cell = null;
//這幾行被注釋掉的代碼,是給表格第一列進(jìn)行一個(gè)賦值起一個(gè)編號(hào)的效果,不過我認(rèn)為沒必要
// if (j == 0) {
// cell = row.createCell(j, HSSFCell.CELL_TYPE_NUMERIC);
// cell.setCellValue(i + 1);
// } else {
cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING);
if (!"".equals(obj[j]) && obj[j] != null) {
cell.setCellValue(obj[j].toString());
}
// }
cell.setCellStyle(style);
}
}
// 讓列寬隨著導(dǎo)出的列長自動(dòng)適應(yīng)
for (int colNum = 0; colNum < columnNum; colNum++) {
int columnWidth = sheet.getColumnWidth(colNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
HSSFRow currentRow;
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(colNum) != null) {
HSSFCell currentCell = currentRow.getCell(colNum);
if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue().getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
if (colNum == 0) {
sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
} else {
sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
}
}
if (workbook != null) {
try {
workbook.write(out);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
}
}
/**
* 列頭單元格樣式
*/
public HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
// 設(shè)置字體
HSSFFont font = workbook.createFont();
// 設(shè)置字體大小
font.setFontHeightInPoints((short) 11);
// 字體加粗
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 設(shè)置字體名字
font.setFontName("Courier New");
// 設(shè)置樣式
HSSFCellStyle style = workbook.createCellStyle();
// 設(shè)置低邊框
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 設(shè)置低邊框顏色
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 設(shè)置右邊框
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 設(shè)置頂邊框
style.setTopBorderColor(HSSFColor.BLACK.index);
// 設(shè)置頂邊框顏色
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在樣式中應(yīng)用設(shè)置的字體
style.setFont(font);
// 設(shè)置自動(dòng)換行
style.setWrapText(false);
// 設(shè)置水平對(duì)齊的樣式為居中對(duì)齊;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
public HSSFCellStyle getStyle(HSSFWorkbook workbook) {
// 設(shè)置字體
HSSFFont font = workbook.createFont();
// 設(shè)置字體大小
font.setFontHeightInPoints((short) 10);
// 字體加粗
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 設(shè)置字體名字
font.setFontName("Courier New");
// 設(shè)置樣式;
HSSFCellStyle style = workbook.createCellStyle();
// 設(shè)置底邊框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
// 設(shè)置底邊框顏色;
style.setBottomBorderColor(HSSFColor.BLACK.index);
// 設(shè)置左邊框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
// 設(shè)置左邊框顏色;
style.setLeftBorderColor(HSSFColor.BLACK.index);
// 設(shè)置右邊框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
// 設(shè)置右邊框顏色;
style.setRightBorderColor(HSSFColor.BLACK.index);
// 設(shè)置頂邊框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 設(shè)置頂邊框顏色;
style.setTopBorderColor(HSSFColor.BLACK.index);
// 在樣式用應(yīng)用設(shè)置的字體;
style.setFont(font);
// 設(shè)置自動(dòng)換行;
style.setWrapText(false);
// 設(shè)置水平對(duì)齊的樣式為居中對(duì)齊;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 設(shè)置垂直對(duì)齊的樣式為居中對(duì)齊;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
//壓縮文件
public void ZipFiles(File[] srcfile, File zipfile) {
ZipOutputStream out = null;
byte[] buf = new byte[1024];
try {
out = new ZipOutputStream(new FileOutputStream(
zipfile));
// out.setEncoding("UTF-8");
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();
} catch (IOException e) {
e.printStackTrace();
}
}
/***
* 刪除指定文件夾下所有文件
*
* @param path 文件夾完整絕對(duì)路徑
* @return
*/
public static boolean delAllFile(String path) {
boolean flag = false;
File file = new File(path);
if (!file.exists()) {
return flag;
}
if (!file.isDirectory()) {
return flag;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
} else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + tempList[i]);// 先刪除文件夾里面的文件
flag = true;
}
}
return flag;
}
}
具體業(yè)務(wù)代碼
注:
1、對(duì)數(shù)據(jù)預(yù)處理
String title = "業(yè)主信息表";//這個(gè)是表格的標(biāo)題,不是文件名
//每個(gè)單元格的標(biāo)題,具體內(nèi)容自己設(shè)置
String[] rowsName = {"業(yè)主id", "姓名","身份證號(hào)","樓棟號(hào)", "單元號(hào)", "樓層號(hào)", "房間號(hào)", "電話號(hào)碼"};
//存放需要的數(shù)據(jù)
ArrayList<Object[]> dataList = new ArrayList<>();
Object[] objs = null;
//根據(jù)業(yè)務(wù)需求,查詢出要導(dǎo)出的數(shù)據(jù)
List<CitRoomMaster> list = citRoomMasterService.getList();
//將全部數(shù)據(jù)按需加載到dataList中
//對(duì)null值進(jìn)行一個(gè)處理,因?yàn)槿绻强盏膶?dǎo)入文件中會(huì)造成整個(gè)文件損壞,讀取不到任何數(shù)據(jù)
for (CitRoomMaster c :list) {
objs = new Object[rowsName.length];
objs[0] = c.getId();
objs[1] = c.getUsername() == null?"未錄入":c.getUsername();
objs[2] = c.getIdCard() == null?"未錄入":c.getIdCard();
objs[3] = c.getBuilding() == null?"未錄入":c.getBuilding();
objs[4] = c.getUnit() == null?"未錄入":c.getUnit();
objs[5] = c.getRoomLevel() == null?"未錄入":c.getRoomLevel();
objs[6] = c.getRoomNum() == null?"未錄入":c.getRoomNum();
objs[7] = c.getTel() == null?"未錄入":c.getTel();
dataList.add(objs);
}
2、按500條數(shù)據(jù)進(jìn)行Excel文件生成
// 將excel導(dǎo)出的文件位置,臨時(shí)文件,注意,一定是一個(gè)不存在的文件,因?yàn)楹竺鏁?huì)把這個(gè)文件夾刪完
String filePath = "C:\\小區(qū)業(yè)主信息"+ File.separator;
// 得到此路徑下文件
File fileDir = new File(filePath);
//創(chuàng)建文件夾
if (!fileDir.exists() && !fileDir.isDirectory()) {
fileDir.mkdirs();
}
// 用于存放生成的excel文件名稱
List<String> fileNames = new ArrayList<String>();
// 導(dǎo)出Excel文件的路徑
String fullFilePath = "";
//輸出流
FileOutputStream os = null;
//拿到整個(gè)需要循環(huán)導(dǎo)出的次數(shù)
int length = list.size()%500 == 0 ? list.size()/500 : (list.size()/500)+1;
for (int i = 0; i < length; i++) {
//給文件命名。隨機(jī)命名 自定義
String fileName = "OwnerInformation-" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
//生成Excel文件導(dǎo)出的路徑
fullFilePath = filePath + File.separator + fileName;
fileNames.add(fullFilePath);
os = new FileOutputStream(fullFilePath);
//調(diào)用poi的工具類
int end = 0;
//對(duì)list進(jìn)行截取,每500條數(shù)據(jù)
ExportExcel ex = new ExportExcel(title, rowsName, dataList.subList(i*500,end = (i+1)*500<=list.size()?(i+1)*500:list.size()));
try {
ex.export(os);
} catch (Exception e) {
e.printStackTrace();
}
os.flush();
os.close();
os = null;
}
3、將存放Excel的文件夾壓縮導(dǎo)出
就完成需求了
//告訴瀏覽器數(shù)據(jù)格式,將頭和數(shù)據(jù)傳到前臺(tái)
String headStr = "attachment; filename=\"" + zip.getName() + "\"";
response.setContentType("APPLICATION/zip");
// response.setHeader("Location",zip.getName());
response.setHeader("Content-Disposition", headStr);
OutputStream out = response.getOutputStream();
InputStream in = new FileInputStream(zipFilePath);
byte[] buffer = new byte[1024];
int i = -1;
while ((i = in.read(buffer)) != -1) {
out.write(buffer, 0, i);
}
out.flush();
out.close();
in.close();
out = null;
try {
excelUtil.delAllFile(filePath); // 刪除完里面所有內(nèi)容
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
myFilePath.delete(); // 刪除空文件夾
} catch (Exception e) {
e.printStackTrace();
}
最后再說一點(diǎn):
- 還是關(guān)于中文亂碼的問題,本來最開始的我是用的中文寫文件名,并且在自己電腦上測(cè)試的時(shí)候是么有亂碼的。
- 但是部署到公司服務(wù)器上,就亂碼了,懷疑是編碼不一致問題導(dǎo)致的,因?yàn)闀r(shí)間問題,也沒有去調(diào)試了。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中避免NullPointerException的方法總結(jié)
這篇文章主要介紹了Java中避免NullPointerException的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-07-07
java實(shí)現(xiàn)對(duì)excel文件的處理合并單元格的操作
這篇文章主要介紹了java實(shí)現(xiàn)對(duì)excel文件的處理合并單元格的操作,開頭給大家介紹了依賴引入代碼,表格操作的核心代碼,代碼超級(jí)簡單,需要的朋友可以參考下2021-07-07
SpringBoot利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下2022-10-10
SpringBoot生成jar/war包的布局應(yīng)用
在 Spring Boot 中,"布局應(yīng)用"(Application Layout)指的是打包生成的可執(zhí)行 jar 或 war 文件中的內(nèi)容組織結(jié)構(gòu),本文給大家介紹了SpringBoot生成jar/war包的布局應(yīng)用,需要的朋友可以參考下2024-02-02
SpringCloud feign微服務(wù)調(diào)用之間的異常處理方式
這篇文章主要介紹了SpringCloud feign微服務(wù)調(diào)用之間的異常處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06

