java后台生成excel,前台发请求下载

为了这个功能找了两天资料,最后还是弄出来了,在此记录一下
我用的 ssm + maven ,操作excel的包是poi-ooxml

maven坐标如下:

	  
		  org.apache.poi
		  poi-ooxml
		  3.9
	  

原理是这样的:

前台发送请求到后台,controller接收后调用生成excel文件的逻辑,此时的excel文件是在内存中的。
如果对此文件的操作是输出流指定地址,如:
	OutputStream out = new FileOutputStream("E:/Members.xls");
则就保存在了本地 e 盘中。因为输出流是new出来的,和浏览器没有任何关系,那如果这一步的输出流来源和浏览器有关系不就有戏了吗?
controller接收的请求是自动带有参数HttpServletResponse的,而且有方法可以获取输出流:

	response.getOutputStream();
然后response要告诉浏览器我这个响应是下载excel文件,所以需要设置一下,如下:
	response.setCharacterEncoding("UTF-8");
	response.setContentType("application/vnd.ms-excel;charset=utf-8");// 设置contentType为excel格式
	response.setHeader("Content-Disposition", "Attachment;Filename="+ fileName+".xls");
其中的fileName是自己定义的,后面的完整代码中有东西。
最后是 最关键的一步,之前看了很多文章都没看到这一步,所以怎么都没成功。
其实很简单,因为到这一步excel文件和response或者说和输出流没有任何关系,所以需要创造这种关系, 如下:
workbook.write(fos);
其中workboo是操作excel的类,fos就是获取的输出流。这样就可以了。

完整的代码:

	@RequestMapping("info")
	public void info(HttpServletRequest request, HttpServletResponse response){
		Map map = new HashMap();
		map.put("sequence", "0001");
		map.put("date", "2018/01/04");
		map.put("chetaihao", "1#");
		map.put("productName", "产品名称");
		map.put("specification", "规格");
		map.put("memo", "备注");
		map.put("inspectRecordBizList", "一个list");

		HSSFWorkbook wb = new HSSFWorkbook();
		Sheet sheet = wb.createSheet("测试表");
		Row row = sheet.createRow(0);
		int i = 0;
		for(String key : map.keySet()){
			Cell cell = row.createCell(i);
			cell.setCellValue((String) map.get(key));
			i++;
		}
		OutputStream fos = null;
		try {
			fos = response.getOutputStream();
			String userAgent = request.getHeader("USER-AGENT");
			String fileName = "test";
			try {
				if(StringUtils.contains(userAgent, "Mozilla")){
					fileName = new String(fileName.getBytes(), "ISO8859-1");
				}else {
					fileName = URLEncoder.encode(fileName, "utf8");
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/vnd.ms-excel;charset=utf-8");// 设置contentType为excel格式
			response.setHeader("Content-Disposition", "Attachment;Filename="+ fileName+".xls");
			wb.write(fos);
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

第一、

map是储存数据的,不想用的话就在后面的for中手动添加单元格的值。map的数据来源可以是像现在的直接添加,也可以是数据库查出来的。它只是储存数据,用list或者其他的也行,只要是往单元格存值时有对应数据就行。

第二、

fileName就像这样自己定义一个或者按照业务需求定义,try-catch的处理是针对不同的浏览器来的,否则文件名可能乱码

第三、

response的几个设置之前说了,是告诉浏览器我这个响应是需要你以下载的方式呈现的。

第四、

workbook写入输出流

第五、

excel的操作。
最后说这个是因为操作excel可以单独成一章,这里简单解释下。excel文件的来源可以是已经存在的文件,通过流读取。也可以是新创建的。操作excel文件就是先创建或者获取sheet(工作表),再创建或者获取row(第几行),再创建或者获取cell(单元格)往cell里面set值或者get值就行。其中涉及合并单元格和单元格样式我没写,资料很多。
网上很多资料用的数据类型,比如List>,其实和map一样,都是存储数据的,可能他们的数据来源是数据库。然后直接生成了一张和他们业务逻辑有关的excel表,所以一开始我没看懂。我现在这个只是创建了一个表头而已,因为主要功能是实现前台发送的请求去下载后台的excel文件,能下载才是我想要的。生成的excel表需要哪些东西再添加。

对了,前台的请求我是用的一个button,绑定点击事件,然后 location.href="xxx" 发送的请求

最后我之所以能弄出来是因为参考这个博客:

http://blog.csdn.net/u014621859/article/details/54944059



LG

你可能感兴趣的:(小功能)