diff --git a/src/main/java/com/biutag/supervision/controller/FileController.java b/src/main/java/com/biutag/supervision/controller/FileController.java index 749a353..3d3c296 100644 --- a/src/main/java/com/biutag/supervision/controller/FileController.java +++ b/src/main/java/com/biutag/supervision/controller/FileController.java @@ -60,6 +60,28 @@ public class FileController { @GetMapping("stream/**") public void download(HttpServletRequest request, HttpServletResponse response) throws IOException { String filePath = request.getRequestURI().substring(12); + String lower = filePath.toLowerCase(); + String range = request.getHeader("Range"); + if (StrUtil.isNotBlank(range) && range.startsWith("bytes=")) { + try (var upstream = fileService.downloadResponse(filePath, range); + InputStream is = upstream.bodyStream()) { + String contentType = Optional.ofNullable(upstream.header("Content-Type")) + .orElseGet(() -> guessContentType(lower)); + response.setContentType(contentType); + response.setHeader("Accept-Ranges", "bytes"); + String contentRange = upstream.header("Content-Range"); + if (StrUtil.isNotBlank(contentRange)) response.setHeader("Content-Range", contentRange); + String contentLength = upstream.header("Content-Length"); + if (StrUtil.isNotBlank(contentLength)) response.setHeader("Content-Length", contentLength); + response.setStatus(upstream.getStatus()); + IoUtil.copy(is, response.getOutputStream()); + return; + } catch (Exception e) { + log.error("Range stream failed, filePath={}, range={}", filePath, range, e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + } if (filePath.toLowerCase().endsWith(".pdf")) { response.setContentType("application/pdf"); } else { @@ -99,4 +121,11 @@ public class FileController { return Result.success(JSONObject.of("html", WordUtil.convertHtml(is))); } + private String guessContentType(String lower) { + if (lower.endsWith(".mp4")) return "video/mp4"; + if (lower.endsWith(".webm")) return "video/webm"; + if (lower.endsWith(".mp3")) return "audio/mpeg"; + if (lower.endsWith(".wav")) return "audio/wav"; + return "application/octet-stream"; + } } diff --git a/src/main/java/com/biutag/supervision/service/FileService.java b/src/main/java/com/biutag/supervision/service/FileService.java index 7e50f65..bb8f154 100644 --- a/src/main/java/com/biutag/supervision/service/FileService.java +++ b/src/main/java/com/biutag/supervision/service/FileService.java @@ -1,6 +1,8 @@ package com.biutag.supervision.service; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import com.biutag.supervision.mapper.FileBase64Mapper; @@ -62,4 +64,14 @@ public class FileService { return httpResponse.bodyStream(); } + + public HttpResponse downloadResponse(String filePath, String range) { + HttpRequest req = HttpUtil.createGet(FDFS_PREVIEW_URL + filePath) + .header("Accept-Encoding", "identity"); + if (StrUtil.isNotBlank(range)) { + req.header("Range", range); + } + return req.execute(); + } + }