對多檔案進行打包後下載(相當於批量下載)
阿新 • • 發佈:2018-12-31
- 頁面:這個頁面我用的是原生的table來產生表格的
//選擇好需要下載的檔案後,觸發事件的按鈕 <input type="button" value="批量下載" onclick="batchDownLoad()"> ... <c:forEach items="${list}" var="fileItem"> <tr> <td> //後臺將檔案的伺服器路徑傳到這 <input id="filePath" value="${fileItem.filePath}" type="hidden"> //後臺將檔案的名稱傳到這 <input id="fileName" value="${fileItem.fileName}" type="hidden"> //這個是為了這裡沒什麼用,不過如果到時候需要定為到這個位置,就可以寫上 <input id="${fileItem.id}" value="${fileItem.id}" type="hidden"> //這是一個選擇需要下載的複選框 <input id="selectIds" value="${fileItem.id}" type="checkbox"> </td> </tr> </c:forEach> ...
- js部分,這裡需要模擬用form表單提交,切記不要用ajax請求,不然瀏覽器就不會接收到後臺傳過來的檔案流,就不能下載了
function batchDownLoad() { var selectIds = []; $("input[name='selectIds']:checked").each(function () { selectIds.push($(this).val()); }); if (selectIds.length<1){ $("#errorMsg").text("請至少選擇一條資訊下載"); return false; } else { $("#errorMsg").text(""); } if (confirm("是否批量下載?")) { var filePaths = []; var fileNames = []; for (var i in selectIds){ var filePath = $("#"+selectIds[i]).parent().find("input:eq(0)").val(); var fileNameTemp = $("#"+selectIds[i]).parent().find("input:eq(1)").val(); var fileName = encodeURIComponent(fileNameTemp); filePaths.push(filePath); fileNames.push(fileName); } //模擬form表單提交 var url = "${ctx}/commom/fileBatch/fileDownLoadBatch"; var form = $("<form></form>").attr("action",url).attr("method","post"); form.append($("<input></input>").attr("type","hidden").attr("name","fileNames").attr("value",fileNames.toString())); form.append($("<input></input>").attr("type","hidden").attr("name","filePaths").attr("value",filePaths.toString())); form.appendTo('body').submit().remove(); } }
- 後臺處理
package com.etc.test; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.sql.Savepoint; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @Controller @RequestMapping(value = "${xxx}/commom/fileBatch") public class FileDownLoadBatchController { private final static String ZIP_NAME = "file.zip";//下載的檔案壓縮包名稱 @RequestMapping(value = "/fileDownLoadBatch") public void fileDownLoadBatch(String[] filePaths, String[] fileNames, HttpServletRequest request, HttpServletResponse response){ //下載的檔案壓縮包名稱 String tmpFileName = ZIP_NAME; /* 1.臨時檔案的存放位置,這個是對頁面中想要下載的檔案,但是該檔案伺服器中已經不存在了,所以需要建立一個空的檔案給使用者,且對該檔案提示已經不存在了,還有將所有問價進行打包後的壓縮包存放的臨時位置 2.這個位置最好自己先在專案中臨時建立一個目錄,裡面放一份檔案,用來提示其他程式設計師說該目錄不要刪除(放上一份提示的檔案還可以在自己測試的時候看該目錄有沒有被編譯出來,因為空的目錄是不會在target中出現的,到時候自己看的時候可能就會被自己誤解了),不過如果你不放的話,可以先判斷下這個目錄是否存在,不存在的話,就建立個.我是在webapp下建立了一個臨時目錄,程式碼如下 String filePathTemp = session.getServletContext().getRealPath("/")+"tempDir" 用這個記得在該方法的引數里加上HttpSession session */ String filePathTemp = "臨時檔案的存放位置,自己設定,記得是伺服器的位置"; byte[] buffer = new byte[1024]; try { //建立臨時壓縮包new FileOutputStream("臨時壓縮包的絕對路徑") ZipOutputStream out = new ZipOutputStream(new FileOutputStream(filePathTemp+ File.separator+tmpFileName)); //下載的檔案集合 for (int i = 0;i<filePaths.length;i++){ String fileName = java.net.URLDecoder.decode(fileNames[i],"UTF-8"); File file = new File(getRealPath(filePaths[i],fileName)); if(file.exists()){//檔案存在 FileInputStream fis = new FileInputStream(getRealPath(filePaths[i],fileName)); out.putNextEntry(new ZipEntry(fileName)); //設定壓縮檔案內的字元編碼,不然會變成亂碼 out.setEncoding("GBK"); int len; //讀取需要下載的檔案內容,打包到zip檔案 while ((len = fis.read(buffer))>0){ out.write(buffer,0,len); } out.closeEntry(); fis.close(); }else {//檔案不存在 File fileTemp = new File(filePathTemp + File.separator + "檔案已被刪除" + fileName); fileTemp.createNewFile(); FileInputStream fis = new FileInputStream(filePathTemp + File.separator + "檔案已被刪除" + fileName); out.putNextEntry(new ZipEntry("檔案已被刪除" + fileName)); //設定壓縮檔案內的字元編碼,不然會變成亂碼 out.setEncoding("GBK"); int len; //讀取需要下載的檔案內容,打包到zip檔案 while ((len = fis.read(buffer)) > 0){ out.write(buffer,0,len); } out.closeEntry(); fis.close(); fileTemp.delete();//清楚臨時建立的檔案 } } out.close(); //將壓縮包返回給介面和刪除臨時建立的壓縮包.上面的步驟只是將檔案打包而已,並沒有傳到瀏覽器,下面的這一步才是向瀏覽器傳輸檔案流 SaveAs(filePathTemp+File.separator+tmpFileName,tmpFileName,request,response); }catch (Exception e){ e.printStackTrace(); } } /** * 獲取目標檔案的絕對路徑 * @param filePath * @param fileName * @return */ private String getRealPath(String filePath,String fileName){ return filePath+File.separator+fileName; } /** * 將壓縮包返回給介面和刪除臨時建立的壓縮包 * @param filePath * @param fileName * @param request * @param getResponse */ public void SaveAs(String filePath,String fileName,HttpServletRequest request,HttpServletResponse getResponse){ try { File file = new File(filePath); //設定交由瀏覽器處理 request.getHeader("User-Agent").toUpperCase(); getResponse.setHeader("Content-Disposition","attachment;filename=\""+new String(fileName.getBytes(),"ISO8859-1")+"\""); getResponse.setContentType("application/zip"); // 讀取檔案 InputStream ins = new FileInputStream(filePath); // 獲取檔案輸出IO流 // 讀取目標檔案,通過response將目標檔案寫到客戶端 OutputStream outs = getResponse.getOutputStream(); //寫檔案 int byteRead = 0; byte[] buffer = new byte[8192]; //開始向網路傳輸檔案流 while ((byteRead = ins.read(buffer))>0){ outs.write(buffer,0,byteRead); } outs.flush();//這裡一定要呼叫flush()方法 ins.close(); outs.close(); //刪除臨時建立的壓縮包 file.delete(); } catch (Exception e) { e.printStackTrace(); } } }