import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.zyh.demo.dao.DeriveMapper;
import com.zyh.demo.domain.Stu;
import com.zyh.demo.service.DeriveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
@Service
@Slf4j
public class DeriveServiceImpl implements DeriveService {
@Autowired
private DeriveMapper deriveMapper;
@Autowired
private HttpServletResponse response;
/**
* 下载数据到 Excel 文件
*
* @throws IOException IO 异常
*/
public void download() throws IOException {
log.info("*********导出开始!**************");
long startTime = System.currentTimeMillis();
String fileName = "downloadBig";
OutputStream outputStream = null;
try {
int totalCount = 10000000; // 总行数
int sheetDataRows = 1000000; // 每个 Sheet 的行数
int writeDataRows = 1000000; // 每次写入的行数
// 获取桌面路径
String filePath = "D:/derive/daochu/" + fileName + ".xlsx";
// 计算需要的 Sheet 数量
Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
// 计算一般情况下每一个 Sheet 需要写入的次数
Integer oneSheetWriteCount = sheetDataRows / writeDataRows;
// 计算最后一个 Sheet 需要写入的次数
Integer lastSheetWriteCount = totalCount % sheetDataRows == 0 ?
oneSheetWriteCount :
(totalCount % sheetDataRows % writeDataRows == 0 ?
(totalCount / sheetDataRows / writeDataRows) :
(totalCount / sheetDataRows / writeDataRows + 1));
outputStream = new FileOutputStream(filePath);
ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
for (int i = 0; i < sheetNum; i++) {
// 创建 Sheet
WriteSheet sheet = new WriteSheet();
sheet.setSheetName("Sheet" + i);
sheet.setSheetNo(i);
for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
// 创建 WriteSheet
WriteSheet writeSheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(Stu.class)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
// 从数据库中提取数据
List<Stu> data = fetchDataFromDatabase(i * sheetDataRows + j * writeDataRows, writeDataRows);
// 将数据写入 Excel
excelWriter.write(data, writeSheet);
}
}
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
log.info("*********导出结束!导出耗时:" + elapsedTime + "毫秒**************");
// 关闭 ExcelWriter
excelWriter.finish();
outputStream.flush();
outputStream.close();
// 返回给前端的响应
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
// 从生成的文件读取内容并写入响应输出流
try (InputStream inputStream = new FileInputStream(filePath);
OutputStream responseOutputStream = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
responseOutputStream.write(buffer, 0, bytesRead);
}
}
// 删除生成的文件
// File file = new File(filePath);
// if (file.exists()) {
// file.delete();
// }
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
outputStream.close();
}
}
}
/**
* 从数据库中获取数据
*
* @param offset 偏移量
* @param limit 限制数量
* @return 数据列表
*/
public List<Stu> fetchDataFromDatabase(int offset, int limit) {
// 调用数据库查询方法以检索数据,注意在 SQL 查询中使用 offset 和 limit
return deriveMapper.stuListWithLimit(offset, limit);
}
/**
* 数据导出接口
*
* @throws IOException IO 异常
*/
@Override
public String derive() throws IOException {
download();
return null;
}
}
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
使用的时候根据实际情况进行调整,比如保存路径记得改
当然千万以下也是可以用的,在总行数的地方改一下,
每个 Sheet 的行数和每次写入的行数可以适当的调整