Java Web實現檔案下載和亂碼處理方法_java

來源:互聯網
上載者:User

檔案上傳和下載是web開發中常遇到的問題,這幾天在做一個項目又用到了檔案下載,之前也零零散散記了些筆記,今天來做一下整理。檔案上傳還有待進一步測試,這裡先說一下檔案下載。

一、檔案下載處理流程

檔案下載處理流程其實很清晰,即:

1、根據檔案名稱或者檔案路徑定位檔案,具體的策略主要根據自己的需求,總之需要系統能找到的檔案全路徑。

2、擷取輸入資料流,從目標檔案擷取輸入資料流。

3、擷取輸出資料流,從response中擷取輸出資料流。

4、從輸入資料流讀入檔案,通過輸出資料流輸出檔案。這是真正的下載執行過程。

5、關閉IO流。

主要流程就是這個,另外就是一些必要的屬性設定,比如比較重要的有設定檔案的contentType類型等。

二、不囉嗦了了,上代碼

我是用Springmvc做的,但其實用其他的也一樣,主要需要HttpServletResponse對象和有效目標檔案。

1、前台代碼

/** 下載上傳的檔案*/function downloadFromUpload(fileName){window.location.href = path + "/download?dir=upload&fileName="+encodeURI(encodeURI(fileName));}/** 普通下載*/function download(fileName){window.location.href = path + "/download?dir=download&fileName="+encodeURI(encodeURI(fileName));}

2、controller代碼

/*** 檔案下載(從上傳路徑下載)* * @param request* @param response* @throws IOException*/@ResponseBody@RequestMapping(value = "/download")public void downloadFile(HttpServletRequest request,HttpServletResponse response, FileModel model) throws Exception {String fileName = URLDecoder.decode(model.getFileName(), "UTF-8");/** 限制只有upload和download檔案夾裡的檔案可以下載*/String folderName = "download";if (!StringUtils.isEmpty(model.getDir())&& model.getDir().equals("upload")) {folderName = "upload";} else {folderName = "download";}String fileAbsolutePath = request.getSession().getServletContext().getRealPath("/")+ "/WEB-INF/" + folderName + "/" + fileName;FileTools.downloadFile(request, response, fileAbsolutePath);log.warn("使用者Id:"+ (Integer) (request.getSession().getAttribute("userId"))+ ",使用者名稱:"+ (String) (request.getSession().getAttribute("username"))+ ",下載了檔案:" + fileAbsolutePath);}

這裡的下載邏輯是,前台只需要請求/download,並給出檔案名稱參數即可。為了避免中文亂碼,前台的檔案名稱在作為參數時,使用了js的encodeURI()將其變為Unicode碼,然後後台解碼轉換為中文。另外由於項目的特殊性,我這裡要下載的檔案可能會在upload和download兩個檔案夾中,所以這裡多了一部分判斷邏輯。另外,我這裡將檔案名稱和請求的檔案夾名稱都封裝在了FileModel中。

3、下載邏輯實現。

這裡沒有用service了,直接用的靜態方法實現。

/*** 下載檔案時指定下載名* * @param request* HttpServletRequest* @param response* HttpServletResponse* @param filePath* 檔案全路徑* @param fileName* 指定用戶端下載時顯示的檔案名稱* @throws IOException*/public static void downloadFile(HttpServletRequest request,HttpServletResponse response, String filePath, String fileName)throws IOException {BufferedInputStream bis = null;BufferedOutputStream bos = null;bis = new BufferedInputStream(new FileInputStream(filePath));bos = new BufferedOutputStream(response.getOutputStream());long fileLength = new File(filePath).length();response.setCharacterEncoding("UTF-8");response.setContentType("multipart/form-data");/** 解決各瀏覽器的中文亂碼問題*/String userAgent = request.getHeader("User-Agent");byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes(): fileName.getBytes("UTF-8"); // fileName.getBytes("UTF-8")處理safari的亂碼問題fileName = new String(bytes, "ISO-8859-1"); // 各瀏覽器基本都支援ISO編碼response.setHeader("Content-disposition",String.format("attachment; filename=\"%s\"", fileName));response.setHeader("Content-Length", String.valueOf(fileLength));byte[] buff = new byte[2048];int bytesRead;while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {bos.write(buff, 0, bytesRead);}bis.close();bos.close();}/*** 下載檔案時不指定下載檔案名稱* * @param request* HttpServletRequest* @param response* HttpServletResponse* @param filePath* 檔案全路徑* @throws IOException*/public static void downloadFile(HttpServletRequest request,HttpServletResponse response, String filePath) throws IOException {File file = new File(filePath);downloadFile(request, response, filePath, file.getName());}

這裡提供了重載的下載方法,解決有時需要指定用戶端下載的檔案名稱的需求。

三、注意事項

1、關於MIME類型的選擇

之前對MIME類型不是很瞭解,發現網上有很多下載的源碼的MIME類型設定的不一樣。即這句

response.setContentType("multipart/form-data");

查了下這裡設定MIME類型的一個作用是告訴用戶端瀏覽器以什麼格式處理要下載的檔案。具體的對應網上有很多講解,這I類設定成這種格式,一般會自動匹配格式。

2、指定用戶端下載檔案名稱

有時我們可能需要指定用戶端下載檔案時的檔案名稱,即這句代碼

response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
中的fileName,可以自訂。前面的部分一般不要動。

3、中文亂碼問題的解決

中文檔案亂碼太常見了,在項目系統架構剛搭建時,就應該統一所有的中文編碼,包括編輯器中、頁面中以及資料庫中,推薦UTF-8編碼。如果用的Spring,還可以配置Spring的字元集過濾器,進一步避免中文亂碼。

(1)用戶端下載請求過程檔案名稱亂碼

有時我們會遇到,前台頁面顯示中文檔案名稱下載列表時正常的,但我們到後台發現請求中的檔案名稱亂碼了,這時採用前面所說的encodeURI可以解決。

(2)用戶端下載執行時檔案名稱亂碼

在實際測試中發現,在其他瀏覽器都可以執行的情況下,ie下中文檔案名稱可能會出現亂碼。在網上看到了這樣一段代碼,經測試,完美解決了不同瀏覽器的中文亂碼問題

/** 解決各瀏覽器的中文亂碼問題*/String userAgent = request.getHeader("User-Agent");byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes(): fileName.getBytes("UTF-8"); // fileName.getBytes("UTF-8")處理safari的亂碼問題fileName = new String(bytes, "ISO-8859-1"); // 各瀏覽器基本都支援ISO編碼response.setHeader("Content-disposition",String.format("attachment; filename=\"%s\"", fileName));

(3)伺服器上檔案亂碼

不同的伺服器可能因平台的不同編碼方式也不同,這裡也需要注意。具體的解決方案請參見之前寫過的一篇文章:檔案下載過程中中文亂碼處理

以上所述是小編給大家介紹的Java Web實現檔案下載和亂碼處理方法,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.