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請求,就會對長度進行限制。

 

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