批量下載
- 引言
- 一、前端JS發送下載請求
- 1、ajax無法發送下載請求
- 2、js發送下載請求:超鏈接方式
- 3、js發送下載請求:拼接Form表單,并提交
- 二、后臺處理
- 三、結束
引言
批量下載思路,首先前端發送下載請求,攜帶必要引數,也可無參默認批量下載頁面全部資料;后臺接收后進行資料處理拿到要下載檔案的下載地址,回圈下載地址,用壓縮流,將檔案直接寫入壓縮包,最后利用檔案下載將壓縮包輸出給前端,
一、前端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, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length);
}
//關閉流
fileInput.close();
// 需要注意的是緩沖流必須要關閉流,否則輸出無效
bufferStream.close();
// 壓縮流不必關閉,使用完后再關
}
三、結束
我也是第一次接觸批量下載,它本身并不難,都只是一些IO的常規操作,沒有彎彎繞繞,只是在實作完整功能的程序中踩到了一些坑,在此記錄一下,以便加深印象和幫助他人吧~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/211678.html
標籤:python
