springMVC實現文件下載功能(解決火狐瀏覽器文件名亂碼問題)

項目中經常遇到文件上傳下載的功能,springMVC裏也提供了文件上傳下載的相關功能,下面直接上代碼,使用springmvc的ResponseEntity實現日誌文件下載。

下載的流程:

1.獲取文件源(我這裏是String類型的文本日誌)

2.將源文件轉化爲對應的輸入流

3.將輸入流讀取到緩衝區

4.設置瀏覽器請求頭信息,請求狀態

5.把流以ResponseEntity的形式返回給客戶端

6.記得關閉流。

然後客戶端就收到流信息就會按照文件下載的方式開了(由於http的頭信息被設置了content-dispostion,所以瀏覽器收到服務端返回的流會以文件保存的方式打開)。

	 	@RequestMapping(value="/downloadLog")
		public ResponseEntity<byte[]> downloadLog(String id,HttpServletRequest request) throws Exception{
			String envName=envService.findEnvironmentById(id).getEnvironmentName()+"log.txt";
			InputStream input=new ByteArrayInputStream(this.getLog(id).getBytes());
			byte[] buff=new byte[input.available()]; // 獲取文件大小
			input.read(buff) ;
			HttpHeaders headers=new HttpHeaders();
		    headers.add("Content-Disposition", "attachment;filename="+URLEncoder.encode(envName, "UTF-8"));
			HttpStatus status=HttpStatus.OK;
			ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(buff,headers,status);
			input.close();
			return  entity;
		}

 

寫完後,測了測,發現在google瀏覽器能上能正常下載且文件名不會亂碼,而在火狐瀏覽器上會亂碼,而文件名是用URLEncoder.encode()方法統一編碼的,所以問題肯定是火狐瀏覽器本身兼容的問題。於是查資料,問題出在其他瀏覽都是統一的unicode編碼,而火狐是iso-8859-1編碼,所以解決方法是:判斷瀏覽器的種類,如果是火狐,重新編碼,修改後的代碼如下:

	@RequestMapping(value="/downloadLog")
		public ResponseEntity<byte[]> downloadLog(String id,HttpServletRequest request) throws Exception{
			String envName=envService.findEnvironmentById(id).getEnvironmentName()+"log.txt";
			InputStream input=new ByteArrayInputStream(this.getLog(id).getBytes());
			byte[] buff=new byte[input.available()]; // input.available()獲取文件大小,並實例化相應大小的字節數組
			input.read(buff) ;//從輸入流中讀取全部字節並存儲到 buff中。
			HttpHeaders headers=new HttpHeaders();
			if(getBrowser(request).equals("FF")){//如果是火狐,解決火狐中文名亂碼問題
				envName = new String(envName.getBytes("UTF-8"),"iso-8859-1");
				headers.add("Content-Disposition", "attachment;filename="
						+ envName);
			}else{
				headers.add("Content-Disposition", "attachment;filename="
						+URLEncoder.encode(envName, "UTF-8"));
			}
			
			HttpStatus status=HttpStatus.OK;
			ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(buff,headers,status);
			input.close();
			return  entity;
		}

// 判斷瀏覽器種類的方法
		private String getBrowser(HttpServletRequest request) {
			String UserAgent = request.getHeader("USER-AGENT").toLowerCase();
			if (UserAgent != null) {
				if (UserAgent.indexOf("msie") >= 0)
					return "IE";
				if (UserAgent.indexOf("firefox") >= 0)
					return "FF";
				if (UserAgent.indexOf("safari") >= 0)
					return "SF";
			}
			return null;
		}

注:判斷l瀏覽器種類寫的不全,可以自行添加更多種類的瀏覽器。

值得注意的是:ajax請求無法響應下載功能因爲response原因,一般請求瀏覽器是會處理服務器輸出的response,例如生成png、文件下載等,然而ajax請求只是個“字符型”的請求,即請求的內容是以文本類型存放的。文件的下載是以二進制形式進行的,雖然可以讀取到返回的response,但只是讀取而已,是無法執行的,說白點就是js無法調用到瀏覽器的下載處理機制和程序。

因此可以通過標籤鏈接的方法直接請求下載地址,或者在js方法裏使用window.location.href等等類似的方法進行下載。

最後看一下效果:

The End~

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