修改文件下载方式,使用StreamingResponseBody,支持大文件下载

This commit is contained in:
WIN-VSNMD38DUOC\Administrator
2024-12-06 17:29:36 +08:00
parent 2ed8e1159c
commit 2e0f8e82a8
3 changed files with 46 additions and 26 deletions

View File

@@ -9,18 +9,24 @@ import cn.somkit.fmt.utils.PathUtils;
import cn.somkit.fmt.utils.RocksDBUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -91,32 +97,45 @@ public class DownloadAction {
return mv;
}
@RequestMapping("/execute")
@ApiOperate(description = "单文件下载")
public void execute(String path, Boolean temp, HttpServletResponse response) throws Exception {
File file = new File(path);
if (!file.isFile()) {
throw new FileNotFoundException("文件不存在");
@ApiOperate(description = "StreamingResponseBody方式下载文件")
@GetMapping(value = "/file", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public DeferredResult<ResponseEntity<StreamingResponseBody>> downloadFileByPath(String path, Boolean temp) throws Exception {
final File file = new File(path);
final DeferredResult<ResponseEntity<StreamingResponseBody>> result = new DeferredResult<>();
if (!file.exists()) {
result.setErrorResult(new RuntimeException("文件不存在"));
return result;
}
String filename = file.getName();
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8));
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.length()));
try (FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream())) {
byte[] buffer_ = new byte[1024];
int n = bufferedInputStream.read(buffer_);
while (n != -1) {
bufferedOutputStream.write(buffer_);
n = bufferedInputStream.read(buffer_);
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.length()));
StreamingResponseBody body = outputStream -> {
try (InputStream inputStream = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
outputStream.flush();
} catch (IOException e) {
throw new RuntimeException("IO错误: " + e.getMessage());
} finally {
if(temp){//删除临时文件
FileSystemUtils.deleteRecursively(new File(path));
// 尝试在流关闭后删除文件
try {
if(temp){
Files.deleteIfExists(file.toPath());
}
} catch (IOException e) {
// 记录日志或采取其他措施
System.err.println("删除文件失败: " + e.getMessage());
}
}
};
result.setResult(new ResponseEntity<>(body, headers, HttpStatus.OK));
return result;
}
@PostMapping("/packZip")

View File

@@ -108,7 +108,7 @@
const fileDown = (obj) => {
const path = obj.getAttribute("value");
window.open(Fmt.ctx() + '/download/execute?path=' + encodeURIComponent(path) + '&temp=' + false);
window.open(Fmt.ctx() + '/download/file?path=' + encodeURIComponent(path) + '&temp=' + false);
};
window.onload = () => {
@@ -139,7 +139,7 @@
};
Fmt.axios(options).then((result) => {
message.update({content: '压缩包' + result.filename + "创建完成,准备下载文件......", result: 'success'}).show();
window.open(Fmt.ctx() + '/download/execute?path=' + encodeURIComponent(result.path) + '&temp=' + true);
window.open(Fmt.ctx() + '/download/file?path=' + encodeURIComponent(result.path) + '&temp=' + true);
}).catch((err) => {
console.log(err);
new axMessage({content: err, result: 'error', iconShow: true}).show();

View File

@@ -23,4 +23,5 @@
修改上传文件目录配置,使其支持使用相对路径
新增临时文件存放地址配置,支持相对路径
新增系统设置页面,支持在线配置上传文件地址、日志文件地址等参数
修改文件下载方式使用StreamingResponseBody支持大文件下载
```