如何解決springmvc文件下載,內容損壞的問題
問題描述:
java 中inputstream流 轉成string,再將String轉換會inputStream,下載下來的文件,內容損壞,例如下載word文檔
使用場景:
底層服務讀取到文件內容獲得InputStream,因為需要多次接口調用,為瞭便於數據傳遞,將InputStream轉換為String字符串進行傳遞,上層服務調用接口,獲取String字符串,在轉換成InputStream進行IO的讀寫操作;
問題原因:
如果文件內容是字符型,這種方法沒有問題,如果不是字符型的,比如MP3,圖片,word文檔等,下載下來會無法打開,如上圖;
解決辦法:
在底層服務InputStream流轉換為String前對二進制數據進行base64加密,然後再轉為String字符串:
public String inputStream2String(InputStream in) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len = 0; byte[] b = new byte[1024]; while ((len = in.read(b, 0, b.length)) != -1) { baos.write(b, 0, len); } byte[] buffer = baos.toByteArray(); //base64加密 return Base64.encodeBase64String(buffer); }
然後上層服務調用接口獲得字符串,再進行base64解密:
Map<String, Object> reMap = gitCodeViewService.gitCodeView(Id, path, version); String content = (String) reMap.get("content"); //用base64進行解碼 byte[] decodeByte = Base64.decodeBase64(content); //將解碼的二進制文件轉換為inputStream InputStream is = new ByteArrayInputStream(decodeByte);
在使用InputStream進行IO的讀寫操作,下載文件內容就正常瞭。
下載文件代碼:
String content = (String) codeViewMap.get("content"); //用base64進行解碼 byte[] decodeByte = Base64.decodeBase64(content); //將解碼的二進制文件轉換為inputStream InputStream is = new ByteArrayInputStream(decodeByte); String userAgent = request.getHeader("User-Agent"); if (userAgent.contains("MSIE") || userAgent.contains("Trident")) { //IE瀏覽器處理 fileName = java.net.URLEncoder.encode(fileName, "UTF-8"); } else { // 非IE瀏覽器的處理: fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); } // 設置文件頭:最後一個參數是設置下載文件名 response.setHeader("Content-Disposition", "attachment;fileName="+fileName); // 設置文件ContentType類型,這樣設置,會自動判斷下載文件類型 response.setContentType("application/octet-stream"); OutputStream os = response.getOutputStream(); // 輸入流輸出流對拷 int len = 0; byte[] b = new byte[1024]; while ((len = is.read(b)) > 0) { os.write(b, 0, len); } os.close(); is.close();
springmvc下載文件遇到的坑
java上傳文件不難,思路也比較清晰,利用SpringMVC就更簡單瞭。
獲取要下載的文件
InputStream in = new FileInputStream(path);
得到輸出流
response.getOutputStream()
設置響應頭
response.setContentType("application/force-download"); response.setHeader("content-disposition","attachment;filename="+filename);
老套路,拷貝數據
int len = 0; byte[] b = new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); }
但是這次我下載文件的時候,寫的沒問題,但是就是一直不能下載,每次都是在頁面輸出瞭二級制流。
也就是得到一片亂碼。找瞭半天,也沒找到哪裡錯瞭。
後來把a標簽的href換瞭,添加瞭一個點擊事件,然後用js中的window.location.href就可以下載瞭。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Java下載文件的四種方式詳細代碼
- springboot中Excel文件下載踩坑大全
- Springboot導出文件,前端下載文件方式
- Java實現PDF在線預覽功能(四種方式)
- Springboot與vue實現數據導出方法具體介紹