需求:

导出大文件,实现以多个线程分别进行写入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);
			}
		}
	}

}