1. 程式人生 > 程式設計 >Java實現批量下載(打包成zip)的實現

Java實現批量下載(打包成zip)的實現

引言

批量下載思路,首先前端傳送下載請求,攜帶必要引數,也可無參預設批量下載頁面全部資料;後臺接收後進行資料處理拿到要下載檔案的下載地址,迴圈下載地址,用壓縮流,將檔案直接寫入壓縮包,最後利用檔案下載將壓縮包輸出給前端。

一、前端JS傳送下載請求

1、ajax無法傳送下載請求

關於下載的常見需求無非就是點選按鈕下載或者選中點選批量下載,點選下載或批量下載後,攜帶引數向後臺傳送下載請求,但是JS中的ajax無法觸發瀏覽器的下載機制,這也是處於安全考慮,所以下載請求不可以通過傳送ajax請求實現。

2、js傳送下載請求:超連結方式

我們可以通過< a >標籤實現,在a標籤的href中拼接get請求並攜帶所需引數,如下

<a href="http://localhost:8080/download/?ids=123,234&fileName=down">下載</a>

批量下載,前端可以傳每條資料的id,用逗號拼接成字串,後臺接收後進行資料處理,然後進行批量下載,但是此方式有侷限性,如果我選中了很多條資料,每條資料的id都是32位UUID,那get請求無法攜帶大量引數,所以這種方式並不適合批量下載,只適合單條資料下載。

3、js傳送下載請求:拼接Form表單,並提交

form表單也有侷限性,例如form表單不能傳輸json格式的資料,也就是說用此方式提交,後臺不能用@RequestBody註解

$('.download-btn').click(function () {
 // 如果要傳選中行的id,則從頁面獲取到所有id,可以拿逗號拼接,放到輸入框傳給後臺
 // 如果需要把選中行整行資料傳到後臺,form表單不支援傳json格式資料,所以可以把
 // 選中行資料放入陣列,轉為json放入輸入框,後臺用String接收,然後再轉回Obj
 var $dataForm = $(
 "<form type='hidden' method='post'>" +
 "<input type='hidden' id='ids' name='ids' value='" + ids + "' type='text'/>" +
 "</form>"
 );
 $dataForm.attr("action",'localhost:8080/download');
 $(document.body).append($dataForm);
 //提交表單,實現下載
 $dataForm.submit();
});

如上邊程式碼所示,傳參為ids,那如果你想傳obj,可以用JSON.stringify()將前端物件或陣列型別轉為json字串,然後賦值給表單的輸入框,一併提交給後臺,後臺用String接收,然後再轉回Object,我在測試過程中 js提交資料到後臺(json)," 被轉譯 成了& quot;,如果你也遇到,請看這篇文章:文章連結

二、後臺處理

此處省略接收引數,獲取需要下載的檔案的url,直接寫死模擬:

@RequestMapping(value = "/download",method = RequestMethod.POST)
public void plistDownLoad(HttpServletResponse response) throws Exception {
 // 此處模擬處理ids,拿到檔案下載url
 List<String> paths = new ArrayList<>();
 paths.add("C:\\Users\\E480\\Desktop\\Study\\casul筆記.txt");
 paths.add("C:\\Users\\E480\\Desktop\\Study\\config配置中心筆記.txt");
 paths.add("C:\\Users\\E480\\Desktop\\Study\\GateWay.txt");
 if (paths.size() != 0) {
 // 建立臨時路徑,存放壓縮檔案
 String zipFilePath = "D:\\workspace-IDEA\\zip\\我的zip.zip";
 // 壓縮輸出流,包裝流,將臨時檔案輸出流包裝成壓縮流,將所有檔案輸出到這裡,打成zip包
 ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
 // 迴圈呼叫壓縮檔案方法,將一個一個需要下載的檔案打入壓縮檔案包
 for (String path : paths) {
  // 該方法在下面定義
  fileToZip(path,zipOut);
 }
 // 壓縮完成後,關閉壓縮流
 zipOut.close();

 //拼接下載預設名稱並轉為ISO-8859-1格式
 String fileName = new String(("我的壓縮檔案.zip").getBytes(),"ISO-8859-1");
 response.setHeader("Content-Disposition","attchment;filename="+fileName);

 //該流不可以手動關閉,手動關閉下載會出問題,下載完成後會自動關閉
 ServletOutputStream outputStream = response.getOutputStream();
 FileInputStream inputStream = new FileInputStream(zipFilePath);
 // 如果是SpringBoot框架,在這個路徑
 // org.apache.tomcat.util.http.fileupload.IOUtils產品
 // 否則需要自主引入apache的 commons-io依賴
 // copy方法為檔案複製,在這裡直接實現了下載效果
 IOUtils.copy(inputStream,outputStream);

 // 關閉輸入流
 inputStream.close();

 //下載完成之後,刪掉這個zip包
 File fileTempZip = new File(zipFilePath);
 fileTempZip.delete();
 }
}

將檔案打包的方法,需要傳一個壓縮路徑,和一個檔案,一次只將一個檔案寫入壓縮包

public static void fileToZip(String filePath,ZipOutputStream zipOut) throws IOException {
 // 需要壓縮的檔案
 File file = new File(filePath);
 // 獲取檔名稱,如果有特殊命名需求,可以將引數列表拓展,傳fileName
 String fileName = file.getName();
 FileInputStream fileInput = new FileInputStream(filePath);
 // 緩衝
 byte[] bufferArea = new byte[1024 * 10];
 BufferedInputStream bufferStream = new BufferedInputStream(fileInput,1024 * 10);
 // 將當前檔案作為一個zip實體寫入壓縮流,fileName代表壓縮檔案中的檔名稱
 zipOut.putNextEntry(new ZipEntry(fileName));
 int length = 0;
 // 最常規IO操作,不必緊張
 while ((length = bufferStream.read(bufferArea,1024 * 10)) != -1) {
 zipOut.write(bufferArea,length);
 }
 //關閉流
 fileInput.close();
 // 需要注意的是緩衝流必須要關閉流,否則輸出無效
 bufferStream.close();
 // 壓縮流不必關閉,使用完後再關
}

三、結束

我也是第一次接觸批量下載,它本身並不難,都只是一些IO的常規操作,沒有彎彎繞繞,只是在實現完整功能的過程中踩到了一些坑,在此記錄一下,以便加深印象和幫助他人吧~~

到此這篇關於Java實現批量下載(打包成zip)的實現的文章就介紹到這了,更多相關Java 批量下載 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!