需求:
导出大文件,实现以多个线程分别进行写入excel,然后通过网络IO输出到浏览器。
CODE:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年7月19日 上午11:38:39
*
*/
@RestController
@CrossOrigin
@RequestMapping("/testJ")
public class TestControllerJ {
@RequestMapping("/testJ.ctrl")
public void test(HttpServletResponse response) throws IOException, Exception {
// 设置MIME类型
response.setHeader("content-type", "application/vbn.ms-excel");
// 设置返回内容以附近的方式下载,并且指定文件名
// java.net.URLEncoder
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode("测试.xlsx", "utf-8"));
ServletOutputStream netOut = response.getOutputStream();
// 创建excel 参数使用list.size()+1 200+1
int size = 201;
SXSSFWorkbook excel = new SXSSFWorkbook(size);
SXSSFSheet sheet = excel.createSheet();
// TODO 线程池写入
Thread thread1 = new Thread(() -> {
try {
testPOI(sheet, 0, 100);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
testPOI(sheet, 100, 200);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
});
thread1.start();
thread2.start();
// 等待线程结束(屏障)
thread1.join();
thread2.join();
// 内存缓冲
ByteArrayOutputStream stream = new ByteArrayOutputStream(size);
excel.write(stream);
// 关闭excel
excel.close();
// 从内存输出到文件 或是网络IO
stream.writeTo(netOut);
netOut.flush();
stream.flush();
netOut.close();
stream.close();
}
/**
* 此处做分页查询,并把查询结果进行写入
*
* @author jangle
* @time 2020年7月19日 下午12:28:29
* @param sheet
* @param start
* @param end
* @throws Exception
*/
private void testPOI(SXSSFSheet sheet, int start, int end) throws Exception {
// TODO 这里做数据库分页查询
for (int i = start+1; i <= end; i++) {
SXSSFRow row = sheet.createRow(i);
for (int j = 0; j < 5; j++) {
SXSSFCell cell = row.createCell(j);
cell.setCellValue(i * j);
}
}
}
}