Excel百万级别数据POI简单导出

springboot+poi导出百万级数据避免OOM内存溢出 记录下在实际项目中碰到过一个重大问题,全量导出百万级数据,由于之前在开发环境数据没有达到百万级别,因此此问题没有处理,上到测试环境后,数据量达到150万的时候,全量导出所有的数据出现内存溢出问题。这段代码亲测有效,到测试环境上导出五百多万条数据都没有出现OOM问题,希望对各位朋友有效。这里实现了多个sheet页导出的数据,excel导出一个sheet最多能导出100万多一点数据,至于具体数字,请朋友们自行百度下。 阅读详情

1.准备工具类

package cn.itcast.utils;

import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@Component
public class DownloadUtil {
	
	/**
	 * @param filePath 要下载的文件路径
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected void download(String filePath,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(new File(filePath), returnName, response, delFlag);
	}


	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected void download(File file,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(file, returnName, response, delFlag);
	}
	
	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	public void prototypeDownload(File file,String returnName,HttpServletResponse response,boolean delFlag){
		// 下载文件
		FileInputStream inputStream = null;
		ServletOutputStream outputStream = null;
		try {
			if(!file.exists()) return;
			response.reset();
			//设置响应类型	PDF文件为"application/pdf",WORD文件为:"application/msword", EXCEL文件为:"application/vnd.ms-excel"。  
			response.setContentType("application/octet-stream;charset=utf-8");

			//设置响应的文件名称,并转换成中文编码
			//returnName = URLEncoder.encode(returnName,"UTF-8");
			returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));	//保存的文件名,必须和页面编码一致,否则乱码
			
			//attachment作为附件下载;inline客户端机器有安装匹配程序,则直接打开;注意改变配置,清除缓存,否则可能不能看到效果
			response.addHeader("Content-Disposition",   "attachment;filename="+returnName);  
			
			//将文件读入响应流
			inputStream = new FileInputStream(file);
			outputStream = response.getOutputStream();
			int length = 1024;
			int readLength=0;
			byte buf[] = new byte[1024];
			readLength = inputStream.read(buf, 0, length);
			while (readLength != -1) {
				outputStream.write(buf, 0, readLength);
				readLength = inputStream.read(buf, 0, length);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				outputStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			//删除原文件
			
			if(delFlag) {				
				file.delete();
			}
		}
	}

	/**
	 * by tony 2013-10-17
	 * @param byteArrayOutputStream 将文件内容写入ByteArrayOutputStream
	 * @param response HttpServletResponse	写入response
	 * @param returnName 返回的文件名
	 */
	public void download(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, String returnName) throws IOException{
		response.setContentType("application/octet-stream;charset=utf-8");
		returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));			//保存的文件名,必须和页面编码一致,否则乱码
		response.addHeader("Content-Disposition",   "attachment;filename=" + returnName);  
		response.setContentLength(byteArrayOutputStream.size());
		
		ServletOutputStream outputstream = response.getOutputStream();	//取得输出流
		byteArrayOutputStream.writeTo(outputstream);					//写到输出流
		byteArrayOutputStream.close();									//关闭
		outputstream.flush();											//刷数据
	}
}

2.准备文本样式

  //大标题的样式
    public CellStyle bigTitle(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short)16);
        font.setBold(true);//字体加粗
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);				//横向居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);		//纵向居中
        return style;
    }

    //小标题的样式
    public CellStyle title(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("黑体");
        font.setFontHeightInPoints((short)12);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);				//横向居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);		//纵向居中
        style.setBorderTop(BorderStyle.THIN);						//上细线
        style.setBorderBottom(BorderStyle.THIN);					//下细线
        style.setBorderLeft(BorderStyle.THIN);						//左细线
        style.setBorderRight(BorderStyle.THIN);						//右细线
        return style;
    }

    //文字样式
    public CellStyle text(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)10);

        style.setFont(font);

        style.setAlignment(HorizontalAlignment.LEFT);				//横向居左
        style.setVerticalAlignment(VerticalAlignment.CENTER);		//纵向居中
        style.setBorderTop(BorderStyle.THIN);						//上细线
        style.setBorderBottom(BorderStyle.THIN);					//下细线
        style.setBorderLeft(BorderStyle.THIN);						//左细线
        style.setBorderRight(BorderStyle.THIN);						//右细线

        return style;
    }

样式不能添加太多 否则会报错

3.实现代码

@RequestMapping("/printExcelMillion")
    public void printExcelMillion(String inputDate) throws Exception {
        List<ContractProductVo> contractProductVoList = contractService.findContractProductVoListByShipTime(inputDate, getCompanyId());
        Workbook workbook = new SXSSFWorkbook();
        Sheet sheet = workbook.createSheet("出货表");
        sheet.setColumnWidth(1,26*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(2,16*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(3,26*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(4,16*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(5,16*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(6,16*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(7,16*256); //1代表一个字母宽度的256分之一
        sheet.setColumnWidth(8,16*256); //1代表一个字母宽度的256分之一
        //开始设置大标题
        Row BigTitleRow = sheet.createRow(0);
        BigTitleRow.setHeightInPoints(36);
        sheet.addMergedRegion(new CellRangeAddress(0,0,1,8));
        Cell cell = BigTitleRow.createCell(1);
        cell.setCellStyle(bigTitle(workbook));
        cell.setCellValue(inputDate.replaceAll("-0","年").replaceAll("-","年")+"月份出货单");

        //开始设置小标题
        Row titleRow = sheet.createRow(1);
        titleRow.setHeightInPoints(26);
        String[] titles = {"客户","合同号","货号","数量","工厂","工厂交期","船期","贸易条款"};
        for (int i = 1; i <= 8; i++) {
            cell = titleRow.createCell(i);
            cell.setCellValue(titles[i-1]);
            cell.setCellStyle(title(workbook));
        }

        //开始设置文本
        Integer rowIndex = 2;
        Row row = null;
        for (ContractProductVo contractProductVo : contractProductVoList) {
            for (int i = 1; i < 6050; i++) {
                row = sheet.createRow(rowIndex);
                row.setHeightInPoints(24);
                //客户	合同号	货号	数量	工厂	工厂交期	船期	贸易条款

                cell = row.createCell(1);
                cell.setCellValue(contractProductVo.getCustomName());

                cell = row.createCell(2);
                cell.setCellValue(contractProductVo.getContractNo());

                cell = row.createCell(3);
                cell.setCellValue(contractProductVo.getProductNo());

                cell = row.createCell(4);
                cell.setCellValue(contractProductVo.getCnumber());

                cell = row.createCell(5);
                cell.setCellValue(contractProductVo.getFactoryName());

                cell = row.createCell(6);
                cell.setCellValue(contractProductVo.getDeliveryPeriod());

                cell = row.createCell(7);
                cell.setCellValue(contractProductVo.getShipTime());

                cell = row.createCell(8);
                cell.setCellValue(contractProductVo.getTradeTerms());

                rowIndex++;
            }
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        workbook.write(byteArrayOutputStream);
        downloadUtil.download(byteArrayOutputStream,response,"出货单.xlsx");
    }

服务器没有大数据量 使用循环来模拟导出大数据

java百万级别数据导入导出如何优化?【篇章一】 【代码】java百万级别数据导入导出如何优化? 阅读详情

相关推荐

百万级数据EXCEL导出--easyexcel

easyexcel 项目git地址为: https://github.com/alibaba/easyexcel 官方使用指南见: https://github.com/alibaba/easyexcel/blob/master/quickstart.md 官方介绍:Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套...

Java_Mrsun的博客 1万+

Java POI 百万规模数据的导入和导出

Java POI 百万规模数据的导入和导出

白白白鲤鱼的博客 5337

Java百万级别数据Excel导出

在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上。

逸轩 1379

百万级数据导出实战:深度对比JavaPOI与EasyExcel的性能优化方案

本文针对Java开发中高频痛点——百万级数据导出场景,深度解析传统POI(HSSF/XSSF/SXSSF)与阿里EasyExcel的核心差异。通过源码级对比揭示内存溢出、性能衰减等问题的根源,提供分页查询、流式写入、多Sheet分片等实战优化策略,并附完整代码实现。实测单次300万数据导出仅91秒,助你从“能用”到“高效稳定”。

Zyw907155124的博客 4210

Java导出数据到excel,数据量百万级别

1.pom支持 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.10-FINAL</vers...

临窗,听雨声 1698

poi导出Excel文件下载数据

poi导出Excel文件下载数据 poi上传Excel文件批量的添加数据 :https://blog.youkuaiyun.com/kangshifu007/article/details/103149764 步骤 : 1.添加依赖 2.添加工具类 , 3.根据实际情况创建相对应的实体类(下面有具体的说明) 4.编写controller层代码 5.service层中的代码省略了 , 只需要根据...

kangshifu007的博客 902

POI百万数据量Excel导出

百万数据POI操作(一) 概述 ​ 我们都知道Excel可以分为早期的Excel2003版本(使用POI的HSSF对象操作)和Excel2007版本(使用POI的XSSF操作),两者对百万数据的支持如下: Excel 2003:在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量。这时对于百万级别数据,Excel肯定容纳不了。 Excel 2...

GG Bond 1181

POI百万级大数据量EXCEL导出 - 请叫我猿叔叔的博客 - 优快云博客.htm

POI百万级大数据量EXCEL导出 - 请叫我猿叔叔的博客 - 优快云博客.htm

使用POI导出百万级数据到excel的解决方案

1.HSSFWorkbook 和SXSSFWorkbook区别 HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls,一张表最大支持65536行数据,256列,也就是说一个sheet页,最多导出6w多条数据 XSSFWorkbook:是操作Excel2007-2010的版本,扩展名是.xlsx对于不同版本的EXCEL文档要使用不同的工具类,如...

weixin_30675967的博客 471

poi_模板导出excel,支持百万级数据模板导出

poi导入、导出,支持百万级数据模板导出、合并excel。项目为spring-boot-2上开发。resource里面有模板,在junit测试类中修改为本地存在路径即可导出文件,在junit测试类中修改for循环的i可以模拟百万级数据导出。注意common-poi使用的SXSSFWorkbook(这个只支持xlsx)支持缓存导出,但是这个只支持简单的for循环导出,模板中的合并单元格那些都未做处理,可能以后会完善。common-poi-no-cache这个支持合并单元格及xls导出。但是大数据量导出性能太低,自己看着用。 注意此版本不支持分页导出,一次性导出大批量数据也会出现内存溢出问题,最新上传的版本支持分页导出,

java导出100万以上excel大数据样例

java导出excel大数据,由于excel本身sheet页存储条数的限制,方案一般有:1、导出多个excel,然后将多个excel压缩为zip包,导出;2、导出可以通过excel打开的文本文件;3、导出csv文件(简单格式的)。 本样例以导出可以打开为excel的文本文件为例,来实现导出大数据的excel,结合stringtemplate模板引擎库,可以避免内存溢出,提高生成效率,理论上生成100万行的数据,用时30-60s。

JAVA使用POI如何导出百万级别数据

用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在64位中没有限制,但是在64位的系统中,性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbo

happyljw的博客 6万+

解决poi大数据量导出excel的代码

解决poi大数据量导出excel的代码,该代码中所用的jar包是poi3.9。在测试过程中单个sheet中导出20万数据没有问题。

Java采用POI优化实现导出excel百万级数据量

1.目前导出excel的几种格式:Excel 2003、Excel 2007 在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量,这时对于百万级别数据,在计算机性能稍低的机器上测试,就很容易导致堆溢出 Excel 2003:在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量。这时对于...

S&Y_shhy_QQ_1127833416 3967

java poi导出大量数据到Excel

java poi导出大量数据到Excel

DAC8568 Controller

DAC8568 ControllerDAC8568 简介串行接口三级目录 DAC8568 简介 PIN Description Name Description LDAC‾\overline{LDAC}LDAC load DACs SYNC‾\overline{SYNC}SYNC 低电平有效,电平触发控制, 该输入为输入数据的帧同步信号. 当SYNC为低,使能DAC内输入移位寄存器,并在随后的所有时钟沿采样数据。 在第32个时钟之后,DAC更新输出。 若不到32个时钟SYNC被置高(即

u010170039的博客 5133

阿里开源(EasyExcel)---导出EXCEL

一. 简介 导出是后台管理系统的常用功能,当数据量特别大的时候会内存溢出和卡顿页面,曾经自己封装过一个导出,POI百万级大数据量EXCEL导出采用了分批查询数据来避免内存溢出和使用SXSSFWorkbook方式缓存数据到文件上以解决下载大文件EXCEL卡死页面的问题。不过一是存在封装不太友好使用不方便的问题,二是这些poi的操作方式仍然存在内存占用过大的问题,三是存在空循环和...

请叫我猿叔叔的博客 5万+

从轻量化到高精度:3DXML 转 STP 的工程数据升级技术指南

本文详细解析了3DXML转STP格式的工程数据升级技术,对比了两种格式在轻量化和高精度方面的特性差异,并提供了CATIA、FreeCAD及Python编程等多种专业级转换方案。通过实际案例展示了如何确保转换过程中的数据精度,适用于CAD设计、精密制造等场景,帮助工程师实现工程数据的高效升级。

weixin_29201859的博客 215

百万级数据excel导出功能如何实现?

最近我做过一个MySQL百万级别数据的excel导出功能,已经正常上线使用了。这个功能挺有意思的,里面需要注意的细节还真不少,现在拿出来跟大家分享一下,希望对你会有所帮助。原始需求:用户在UI界面上点击全部导出按钮,就能导出所有商品数据。咋一看,这个需求挺简单的。但如果我告诉你,导出的记录条数,可能有一百多万,甚至两百万呢?这时你可能会倒吸一口气。如果同步导数据,接口很容易超时。如果把所有数据一次性装载到内存,很容易引起OOM。数据量太大sql语句必定很慢。

5525

手把手教你用Docker快速部署ZLMediaKit流媒体服务器(含WebRTC配置)

本文详细介绍了如何使用Docker快速部署ZLMediaKit流媒体服务器,并配置WebRTC功能。通过容器化部署,实现环境一致性、资源隔离和快速扩展,同时提供WebRTC专项配置、多协议推拉流实战测试及生产环境优化建议,帮助开发者高效搭建企业级流媒体平台。

agile9scrum的博客 203

利用kettle进行数据库数据比对

Kettle是一款国外开源的ETL工具,纯java编写,可以在Windows、Linux、Unix上运行,数据抽取高效稳定。本人用的版本是6.1。 之前用kettle这个开源的ETL工具是用来做数据抽取的,这次测试有个需求,是做数据库数据的比对。验证源表到目标表的逻辑正确,从而利用源表自己写SQL逻辑,生成的结果和目标表去比对。这次想到了利用kettle的数据比较功能,来做这些数据校验。 ...

多米诺DU的专栏 1万+

JAVA使用POI导出百万级别数据

用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在64位中没有限制,但是在64位的系统中,性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式的Excel文件。 这里普及一下,在POI中使用HSSF对象时,ex

gordon 700

【超详细】C#的单例模式

本文详细介绍了C#中的单例设计模式,包括两种实现方式:普通类泛型单例(Singleton<T>)和基于MonoBehaviour的组件单例(MonoSingleton<T>)。单例模式通过私有构造、静态私有实例和公共访问入口确保全局唯一实例,具有节省资源、保证数据一致性等优势。文章分别阐述了两者的核心原理、代码实现、使用场景及注意事项,并提供了日志管理器和音效管理器的具体应用示例。特别强调了多线程安全、初始化时机和避免过度使用等重要原则,为Unity开发中合理运用单例模式提供了全面指导。

grapefruit_lyy的博客 1535
下一篇: 使用EasyExcel简单操作Excel
施先生不轻
博客等级 码龄6年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值