項目中經常遇到文件上傳下載的功能,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~