POST请求导出Excel

目的:使用POST请求导出Excel文档。

起因:在使用Java导出Excel时,笔者在上一篇文章中使用的导出POJO或者BSONDocument类型的Excel文档的方法,其实使用的是GET请求,因为当时前端传的参数也不多,并不会因为浏览器对GET请求参数的长度的限制而导致请求失败。

但是,在实际中,可能经常遇见过滤导出这种要求。比如,选择了过滤条件,导出过滤之后的数据,那么这个时候,如果不做前端导出,就有两种方式交给后端导出:①将过滤之后的表格数据全部传给后端 ,让后端导出②将过滤条件传给后端,后端解析并且自己搜索出所有的数据再导出。而无论是这两种的任何一种方式,GET请求都可能满足不了参数的长度,所以需要使用POST方式,在请求体中,把数据或者过滤条件传给后端。而如果继续使用笔者上一篇文章的导出方法,那么前端最后导出的就不再是文件,而会显示出一页乱码(乱码其实就是导出的数据,只是解析方式错误)。

解决方案:①:前端使用JS对后端返回的数据进行处理(最终还是变成了前端导出,数据量过大则为导致前端导出很卡,不建议使用)②:后端处理,其实笔者使用过两种后端处理方式,因为最近发现了第二种方式,充分让笔者认识到自己知识的不足、狭隘,才准备写这篇文章(说多了都是泪)。

在讲第二种方式之前,说下以前笔者如何处理过滤导出这种要用POST请求导出Excel类型的方法:利用缓存服务器,前端先调用post把数据或者过滤条件给后端,后端获取数据将数据存入redis,然后返回成功状态给前端,前端再调用GET请求,参数是redis里面的保存数据的key,这样,后端通过key再从redis获取数据并导出(现在笔者已经不忍直视了。。。。)

接下来就是第二种方式(超级无敌简单到爆),下面贴上一个关键代码:

response.setContenType("selfdefinition");内容类型设置为自定义类型,即不能与约定好的类型相同,随便输字符串,如:sbsbsbsbsbsbssb。关于这个响应头,在上一篇文章结尾处有比较详细的说明,包括作用。

	/**
	 * 导出excel表格数据
	 * @param datas 需要导出的数据模型集合
	 * @param specialFields 需要特殊处理的字段,比如这个字段需要加上超链接
	 * @param excelName 导出Excel文件名
	 * @param tableHeaders 表格数据模型与表头信息键值对
	 * @param response 响应
     * @param requestType 请求的方式
	 */
	public static <T> void excelExport(List<T> datas, List<KeyValueVO> specialFields, String excelName, 
			List<KeyValueVO> tableHeaders, HttpServletResponse response, String requestType)
	{
		//如果需要导出的数据或者表头信息为空等,则返回
		if (null == datas || datas.isEmpty() || tableHeaders == null || tableHeaders.isEmpty()) 
		{
			return;
		}
		try 
		{
			excelName = new String(excelName.getBytes("UTF-8"),"ISO-8859-1");
		} 
		catch (Exception e1) 
		{
			e1.printStackTrace();
		}
		
		if ("post".equals(requestType))
        {
            //笔者亲测,如果响应头设置响应类型为自定义类型,就是随便输一个字符串,
            //不能与规定的相同,那么某些浏览器默认会表示下载文件,
            //这样就能下载你返回的数据了,而不是显示乱码
            response.setContenType("selfdefinition");

        }
        else
        {
            response.setContenType("application/vnd.ms-excel;charset=UTF-8");
        }

        response.setHeader("Content-disposition", "atachment;filename=" + excelName +     ".xls");
		response.setCharacterEncoding("utf-8");
		
		try 
		{
			writeExcel(datas,specialFields,excelName,tableHeaders,response);
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

如果看过笔者上一篇文章的读者可能晓得,这里贴的代码和笔者上一篇导出的代码基本相同,只是方法多了一个参数,就是请求的类型,然后根据请求的类型,设置响应的请求头,如果是post请求,请求头的contentType这个值,就不要设置以前的值了,设置一个自定义的值就行。这样,部分浏览器因为识别不了这个类型,就会默认下载文件。于是,post请求,在前后端不做任何处理的情况下也能直接下载Excel了。

这里贴出部分浏览器对各种响应类型的反应:

另外,笔者使用的GOOGLE浏览器,该浏览器对无法识别的自定义类型也会出现下载文件。

最后,笔者想说的就是,其实HTTP协议,就是数据的传输,其他任何操作都是浏览器各种工具约定好的,HTTP协议只负责传输数据,至于这个数据如何解析,渲染,用什么方式,都是浏览器规定的,包括,我们常说的GET请求,参数不能过长,其实HTTP并没有约定GET请求参数的长度,你想多长就多长,只是浏览器约定了,如果是GET请求,就会对长度进行限制。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章