一. 后端
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Controller
@RequestMapping("/file")
public class FileDownLoadController {
@RequestMapping("/init")
public ModelAndView init() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("fileDownload");
return modelAndView;
}
@GetMapping("/getFileName")
@ResponseBody
public String getFileName() {
String fileName = Stream.of("1.txt", "2.txt", "3.txt")
.collect(Collectors.joining(","));
return fileName;
}
@GetMapping("/manyFileDownLoad/{fileName}")
public void manyFileDownLoad(@PathVariable("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
File file = new File("C:\\Users\\xxx\\Desktop\\downloadFile\\" + fileName);
FileInputStream fileInputStream = null;
try {
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
fileInputStream = new FileInputStream(file);
OutputStream os = response.getOutputStream();
os.write(fileInputStream.readAllBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
}
}
}
二. 前端
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<button id="btn">点击同时下载多个文件</button>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" referrerpolicy="no-referrer"></script>
<script th:inline="javascript">
const waitTime = async (milliseconds) => await new Promise((resolve) => setTimeout(resolve, milliseconds));
const ctxPath = [[${#httpServletRequest.getContextPath()}]];
const url = `${ctxPath}/file`;
$("#btn").click(async () => {
const response = await fetch(url + '/getFileName');
const result = await response.text();
const fileNameList = result.split(",");
const fileBlobList = [];
for (const fileName of fileNameList.values()) {
const response = await fetch(`${url}/manyFileDownLoad/${fileName}`);
const cloneRes = response.clone();
const file = await response.blob();
fileBlobList.push(new Blob([file]));
for (const [key, value] of cloneRes.headers) {
if (key !== "content-disposition") {
continue;
}
console.log(value.split(";")[1])
}
}
const aElement = document.createElement('a');
aElement.style.display = 'none';
document.body.appendChild(aElement);
for (const [index, fileBlob] of fileBlobList.entries()) {
const src = URL.createObjectURL(fileBlob);
aElement.href = src;
aElement.download = fileNameList[index];
aElement.click();
URL.revokeObjectURL(src);
await waitTime(800);
}
document.body.removeChild(aElement);
})
</script>
</html>
三. 效果