diff --git a/src/main/java/cn/somkit/fmt/action/DownloadAction.java b/src/main/java/cn/somkit/fmt/action/DownloadAction.java index f27ff78..8587e50 100644 --- a/src/main/java/cn/somkit/fmt/action/DownloadAction.java +++ b/src/main/java/cn/somkit/fmt/action/DownloadAction.java @@ -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> downloadFileByPath(String path, Boolean temp) throws Exception { + final File file = new File(path); + final DeferredResult> 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); + } + outputStream.flush(); + } catch (IOException e) { + throw new RuntimeException("IO错误: " + e.getMessage()); + } finally { + // 尝试在流关闭后删除文件 + try { + if(temp){ + Files.deleteIfExists(file.toPath()); + } + } catch (IOException e) { + // 记录日志或采取其他措施 + System.err.println("删除文件失败: " + e.getMessage()); + } } - } catch (Exception e) { - e.printStackTrace(); - } finally { - if(temp){//删除临时文件 - FileSystemUtils.deleteRecursively(new File(path)); - } - } + }; + + result.setResult(new ResponseEntity<>(body, headers, HttpStatus.OK)); + return result; } @PostMapping("/packZip") diff --git a/src/main/resources/templates/download.html b/src/main/resources/templates/download.html index 40bb8e4..dbd5214 100644 --- a/src/main/resources/templates/download.html +++ b/src/main/resources/templates/download.html @@ -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(); diff --git a/版本记录/readme.md b/版本记录/readme.md index 42f00c8..458ab33 100644 --- a/版本记录/readme.md +++ b/版本记录/readme.md @@ -23,4 +23,5 @@ 修改上传文件目录配置,使其支持使用相对路径 新增临时文件存放地址配置,支持相对路径 新增系统设置页面,支持在线配置上传文件地址、日志文件地址等参数 + 修改文件下载方式,使用StreamingResponseBody,支持大文件下载 ``` \ No newline at end of file