- 限速下载 通过设置请求头来限制下载速度,可以防止服务器过于快速地传输文件,保护带宽和服务器资源。我们可以使用
HttpServletResponse对象的setHeader方法来设置相应的请求头。
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 设置文件名和内容类型
String fileName = "example.pdf"
String contentType = "application/octet-stream"
// 设置限速速率
int rate = 1024
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 获取文件输入流
InputStream inputStream = new FileInputStream(new File("path/to/file"))
// 获取文件输出流
OutputStream outputStream = response.getOutputStream()
byte[] buff = new byte[1024]
int bytesRead
// 设置限速
long startTime = System.currentTimeMillis()
while ((bytesRead = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, bytesRead)
// 计算下载速度
long currentTime = System.currentTimeMillis()
long elapsedTime = currentTime - startTime
int downloadRate = (int) ((outputStream.getChannel().position() / elapsedTime) * 1000)
// 如果当前下载速度大于限速速率,进行限速
if (downloadRate > rate) {
Thread.sleep(1000)
startTime = System.currentTimeMillis()
}
}
outputStream.flush()
outputStream.close()
inputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
- 多线程加速下载 通过创建多个线程来同时下载文件的不同部分,从而提高下载速度。我们可以使用Java的多线程技术来实现。以下是一个实现多线程下载的示例代码。
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 设置文件名和内容类型
String fileName = "example.pdf"
String contentType = "application/octet-stream"
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 获取文件输入流
InputStream inputStream = new FileInputStream(new File("path/to/file"))
// 获取文件输出流
OutputStream outputStream = response.getOutputStream()
byte[] buff = new byte[1024]
int bytesRead
// 创建下载线程
DownloadThread[] threads = new DownloadThread[3]
for (int i = 0
threads[i] = new DownloadThread(inputStream, outputStream, buff)
threads[i].start()
}
// 等待所有线程下载完成
for (DownloadThread thread : threads) {
thread.join()
}
outputStream.flush()
outputStream.close()
inputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
class DownloadThread extends Thread {
private InputStream inputStream
private OutputStream outputStream
private byte[] buff
public DownloadThread(InputStream inputStream, OutputStream outputStream, byte[] buff) {
this.inputStream = inputStream
this.outputStream = outputStream
this.buff = buff
}
@Override
public void run() {
int bytesRead
try {
while ((bytesRead = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, bytesRead)
}
inputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
}
- ZIP压缩下载 将文件压缩成ZIP格式,然后提供下载链接。我们可以使用
java.util.zip包中提供的类来实现文件的压缩和下载。
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 设置文件名和内容类型
String fileName = "example.zip"
String contentType = "application/octet-stream"
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 获取文件输出流
OutputStream outputStream = response.getOutputStream()
// 创建ZIP输出流
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)
// 添加文件到ZIP压缩文件
File file1 = new File("path/to/file1")
File file2 = new File("path/to/file2")
addToZipFile(file1, zipOutputStream)
addToZipFile(file2, zipOutputStream)
zipOutputStream.close()
outputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
private void addToZipFile(File file, ZipOutputStream zipOutputStream) throws IOException {
FileInputStream fileInputStream = new FileInputStream(file)
ZipEntry zipEntry = new ZipEntry(file.getName())
zipOutputStream.putNextEntry(zipEntry)
byte[] buff = new byte[1024]
int bytesRead
while ((bytesRead = fileInputStream.read(buff)) != -1) {
zipOutputStream.write(buff, 0, bytesRead)
}
fileInputStream.close()
}
- 导出Excel 将数据导出为Excel文件,并提供下载链接。我们可以使用开源库Apache POI来操作Excel文件。
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 设置文件名和内容类型
String fileName = "example.xlsx"
String contentType = "application/octet-stream"
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 创建工作簿
Workbook workbook = new XSSFWorkbook()
// 创建工作表
Sheet sheet = workbook.createSheet("Sheet1")
// 创建单元格并设置数据
Row headerRow = sheet.createRow(0)
headerRow.createCell(0).setCellValue("Name")
headerRow.createCell(1).setCellValue("Age")
Row dataRow = sheet.createRow(1)
dataRow.createCell(0).setCellValue("John")
dataRow.createCell(1).setCellValue(25)
// 将工作簿写入输出流
OutputStream outputStream = response.getOutputStream()
workbook.write(outputStream)
workbook.close()
outputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
- 使用byte数组 直接将文件内容存储在byte数组中,然后通过输出流将byte数组写入响应。
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 设置文件名和内容类型
String fileName = "example.txt"
String contentType = "text/plain"
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 读取文件内容到byte数组
byte[] fileContent = Files.readAllBytes(Paths.get("path/to/file"))
// 获取文件输出流
OutputStream outputStream = response.getOutputStream()
// 将byte数组写入输出流
outputStream.write(fileContent)
outputStream.flush()
outputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
- 使用文件流 使用文件流直接将文件内容写入响应。
@GetMapping("/download")
public void download(HttpServletResponse response) {
String fileName = "example.txt";
String contentType = "text/plain";
response.setHeader("Content-Disposition", "attachment; filename="" + fileName + """);
response.setContentType(contentType);
try {
InputStream inputStream = new FileInputStream(new File("path/to/file"));
OutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream, outputStream);
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
- 使用ResourceLoader 使用Spring提供的
ResourceLoader来加载文件,并将文件内容写入响应。
@GetMapping("/download")
public void download(HttpServletResponse response, ResourceLoader resourceLoader) {
// 设置文件名和内容类型
String fileName = "example.txt"
String contentType = "text/plain"
response.setHeader("Content-Disposition", "attachment
response.setContentType(contentType)
try {
// 使用ResourceLoader加载文件
Resource resource = resourceLoader.getResource("classpath:path/to/file")
// 获取文件输入流
InputStream inputStream = resource.getInputStream()
// 获取文件输出流
OutputStream outputStream = response.getOutputStream()
// 将文件内容写入输出流
IOUtils.copy(inputStream, outputStream)
outputStream.flush()
outputStream.close()
inputStream.close()
} catch (Exception e) {
e.printStackTrace()
}
}
- 使用StreamingResponseBody 使用Spring提供的
StreamingResponseBody接口来实现异步下载,提高系统的并发能力。
@GetMapping("/download")
public ResponseEntity<StreamingResponseBody> download() {
String fileName = "example.txt";
String contentType = "text/plain";
return ResponseEntity
.ok()
.header("Content-Disposition", "attachment; filename="" + fileName + """)
.contentType(MediaType.parseMediaType(contentType))
.body(outputStream -> {
try {
InputStream inputStream = new FileInputStream(new File("path/to/file"));
byte[] buff = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, bytesRead);
}
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
});
}
- 使用ResponseEntity 使用Spring提供的
ResponseEntity类来实现下载,将文件内容包装为HttpEntity对象返回。
@GetMapping("/download")
public ResponseEntity<byte[]> download() {
String fileName = "example.txt";
String contentType = "text/plain";
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename="" + fileName + """);
headers.setContentType(MediaType.parseMediaType(contentType));
try {
byte[] fileContent = Files.readAllBytes(Paths.get("path/to/file"));
return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}