JAVA后臺(tái)實(shí)現(xiàn)文件批量下載方式
JAVA后臺(tái)實(shí)現(xiàn)文件批量下載
工具類
/**
* 本地文件路徑
*/
private static final String FILE_PATH = "F:\\test";
/**
* 批量下載文件
*
* @param list 批量文件集合(前端只傳id集合,后端去查數(shù)據(jù)庫拿到文件信息)
* @param request request
* @param response response
* @param <T> 實(shí)體類 extends BaseEntityPoJo
*/
public static <T extends BaseEntityPoJo> void batchDownloadFile(List<T> list, HttpServletRequest request, HttpServletResponse response) {
//設(shè)置響應(yīng)頭信息
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
//設(shè)置壓縮包的名字,date為時(shí)間戳
String date = DateUtil.formatDateTimeSecond(new Date());
String downloadName = "壓縮包" + date + ".zip";
//返回客戶端瀏覽器的版本號(hào)、類型
String agent = request.getHeader("USER-AGENT");
try {
//針對(duì)IE或者以IE為內(nèi)核的瀏覽器:
if (agent.contains("MSIE") || agent.contains("Trident")) {
downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
} else {
//非IE瀏覽器的處理:
downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
} catch (Exception e) {
e.printStackTrace();
}
response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");
//設(shè)置壓縮流:直接寫入response,實(shí)現(xiàn)邊壓縮邊下載
ZipOutputStream zipOs = null;
//循環(huán)將文件寫入壓縮流
DataOutputStream os = null;
//文件
File file;
try {
zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
//設(shè)置壓縮方法
zipOs.setMethod(ZipOutputStream.DEFLATED);
//遍歷文件信息(主要獲取文件名/文件路徑等)
for (T t : list) {
try {
//文件名(包含后綴名,如:測(cè)試.pdf)
Field field = t.getClass().getDeclaredField("name");
field.setAccessible(true);
String name = field.get(t).toString();
//本地文件路徑(絕對(duì)路徑,包含后綴名,如:F:\\test\\測(cè)試.pdf),這里是在windows上測(cè)試的,路徑是反斜杠
String path = FILE_PATH + File.separator + name;
log.info("batchDownloadFile:[filePath:{}]", path);
file = new File(path);
if (!file.exists()) {
throw new RuntimeException("文件不存在");
}
//添加ZipEntry,并將ZipEntry寫入文件流
zipOs.putNextEntry(new ZipEntry(name));
os = new DataOutputStream(zipOs);
FileInputStream fs = new FileInputStream(file);
byte[] b = new byte[100];
int length;
//讀入需要下載的文件的內(nèi)容,打包到zip文件
while ((length = fs.read(b)) != -1) {
os.write(b, 0, length);
}
//關(guān)閉流
fs.close();
zipOs.closeEntry();
//==============此處如果是網(wǎng)絡(luò)文件路徑,可按如下方式讀取=============
/*
//文件名(包含后綴名,如:測(cè)試.pdf)
Field field = t.getClass().getDeclaredField("name");
field.setAccessible(true);
String name = field.get(t).toString() + ".pdf";
//網(wǎng)絡(luò)文件路徑(瀏覽器可直接訪問的路徑,如:http://192.168.0.12/frame-service-gengbao/document/四川省2022第四季度報(bào)告.pdf)
Field urlField = t.getClass().getDeclaredField("url");
urlField.setAccessible(true);
URL url = new URL(urlField.get(t).toString());
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
//添加ZipEntry,并將ZipEntry寫入文件流
zipOs.putNextEntry(new ZipEntry(name));
os = new DataOutputStream(zipOs);
byte[] b = new byte[100];
int length;
//讀入需要下載的文件的內(nèi)容,打包到zip文件
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
zipOs.closeEntry();
*/
} catch (IllegalAccessException | NoSuchFieldException e) {
log.error("下載文件出錯(cuò)![{}]", e.getMessage());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//關(guān)閉流
try {
if (os != null) {
os.flush();
os.close();
}
if (zipOs != null) {
zipOs.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
控制層
/**
* 批量下載(測(cè)試時(shí)可改為GET請(qǐng)求,瀏覽器直接調(diào)用接口)
*
* @param ids 用于查詢相關(guān)表獲取文件信息
* @param request request
* @param response response
*/
@GetMapping("/batchDownloadFile")
@ApiOperation("批量下載")
public void batchDownloadFile(@RequestParam("ids") final String ids,
HttpServletRequest request,
HttpServletResponse response) {
log.info("downloadPlanFile:批量下載[ids:{},request:{},response:{}]", ids, request, response);
List<Integer> idList = ControllerHelper.splitToLong(ids);
List<RegulatoryReport> list = service.list(idList);
FileUtil.batchDownloadFile(list, request, response);
}
上面用到的方法
分割字符串
public static List<Integer> splitToLong(final String str) {
return StringUtils.isEmpty(str) ? Collections.emptyList() : Stream.of(str.split(",")).map(Integer::valueOf).collect(Collectors.toList());
}
獲取時(shí)間戳
/**
* 將日期解析成yyyyMMddHHmmss的字符串
*
* @param date the date
* @return the string
*/
public static String formatDateTimeSecond(Date date) {
if (date == null) {
return "";
}
return new SimpleDateFormat(DATETIME_STAMP_SECOND, Locale.CHINA).format(date);
}
注意:
我這里為了對(duì)各種文件通用下載,工具類用的泛型方法,如果不需要泛型的,直接傳入自己需要的實(shí)體類集合就可以了。
測(cè)試接口


其他記錄
在Java中,當(dāng)變量的數(shù)據(jù)類型為File時(shí),值的斜杠都是“\”(new File(filePath), 就會(huì)變成xx\xx\1.txt);
當(dāng)變量的數(shù)據(jù)類型為String 時(shí),斜杠都是“/”(String filePath = “xx/xx/1.txt”);
File f = new File(filePath); String path = (f+“”).replaceAll(“\\”, “/”);
把f轉(zhuǎn)成String類型,然后把里面的“\”替換成“/”就行了。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springcloud?gateway實(shí)現(xiàn)簡易版灰度路由步驟詳解
這篇文章主要為大家介紹了springcloud?gateway實(shí)現(xiàn)簡易版灰度路由步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
spring cloud config分布式配置中心的高可用問題
本文給大家介紹spring cloud config分布式配置中心的高可用問題,通過整合Eureka來實(shí)現(xiàn)配置中心的高可用,需要的朋友參考下本文2018-01-01
Java并發(fā)程序刺客之假共享的原理及復(fù)現(xiàn)
前段時(shí)間在各種社交平臺(tái)“雪糕刺客”這個(gè)詞比較火,而在并發(fā)程序中也有一個(gè)刺客,那就是假共享。本文將通過示例詳細(xì)講解假共享的原理及復(fù)現(xiàn),需要的可以參考一下2022-08-08
Java實(shí)現(xiàn)雙保險(xiǎn)線程的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)雙保險(xiǎn)線程的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
java中VO PO DTO POJO BO DO對(duì)象的應(yīng)用場(chǎng)景及使用
文章介紹了Java開發(fā)中常用的幾種對(duì)象類型及其應(yīng)用場(chǎng)景,包括VO、PO、DTO、POJO、BO和DO等,并通過示例說明了它們?cè)诓煌瑘?chǎng)景下的應(yīng)用2025-01-01

