Commit 2ad1001e94c75aa423da7095546b18af68c3e837

Authored by 648540858
1 parent 8679ad21

修复录像并发下载内存占用过多的问题

src/main/java/top/panll/assist/config/WebMvcConfig.java 0 → 100644
  1 +package top.panll.assist.config;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  6 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  7 +import top.panll.assist.dto.UserSettings;
  8 +
  9 +import java.io.File;
  10 +
  11 +
  12 +@Configuration
  13 +public class WebMvcConfig extends WebMvcConfigurerAdapter {
  14 +
  15 + @Autowired
  16 + private UserSettings userSettings;
  17 +
  18 + @Override
  19 + public void addResourceHandlers(ResourceHandlerRegistry registry) {
  20 + File file = new File(userSettings.getRecord());
  21 + registry.addResourceHandler("/download/**").addResourceLocations("file://" + file.getAbsolutePath() + "/");
  22 + super.addResourceHandlers(registry);
  23 + }
  24 +}
... ...
src/main/java/top/panll/assist/controller/DownloadController.java
1   -package top.panll.assist.controller;
2   -
3   -
4   -import io.swagger.v3.oas.annotations.Operation;
5   -import io.swagger.v3.oas.annotations.Parameter;
6   -import io.swagger.v3.oas.annotations.tags.Tag;
7   -import org.apache.catalina.connector.ClientAbortException;
8   -import org.slf4j.Logger;
9   -import org.slf4j.LoggerFactory;
10   -import org.springframework.beans.factory.annotation.Autowired;
11   -import org.springframework.stereotype.Controller;
12   -import org.springframework.web.bind.annotation.*;
13   -import top.panll.assist.dto.UserSettings;
14   -import top.panll.assist.utils.PageInfo;
15   -
16   -import javax.servlet.http.HttpServletRequest;
17   -import javax.servlet.http.HttpServletResponse;
18   -import java.io.BufferedOutputStream;
19   -import java.io.File;
20   -import java.io.IOException;
21   -import java.io.RandomAccessFile;
22   -import java.nio.charset.StandardCharsets;
23   -import java.util.List;
24   -import java.util.Map;
25   -
26   -@Controller
27   -@RequestMapping("/download")
28   -public class DownloadController {
29   -
30   - private final static Logger logger = LoggerFactory.getLogger(DownloadController.class);
31   -
32   - @Autowired
33   - private UserSettings userSettings;
34   -
35   - /**
36   - * 获取app+stream列表
37   - *
38   - * @return
39   - */
40   - @GetMapping(value = "/**")
41   - @ResponseBody
42   - public void download(HttpServletRequest request, HttpServletResponse response) {
43   -
44   - String resourcePath = request.getServletPath();
45   - System.out.println(resourcePath);
46   - resourcePath = resourcePath.substring("/download".length() + 1, resourcePath.length());
47   - String record = userSettings.getRecord();
48   -// if (record.endsWith("/")) {
49   -// record = record.substring(0, record.length() - 1);
50   -// System.out.println(record);
  1 +//package top.panll.assist.controller;
  2 +//
  3 +//
  4 +//import io.swagger.v3.oas.annotations.Operation;
  5 +//import io.swagger.v3.oas.annotations.Parameter;
  6 +//import io.swagger.v3.oas.annotations.tags.Tag;
  7 +//import org.apache.catalina.connector.ClientAbortException;
  8 +//import org.slf4j.Logger;
  9 +//import org.slf4j.LoggerFactory;
  10 +//import org.springframework.beans.factory.annotation.Autowired;
  11 +//import org.springframework.stereotype.Controller;
  12 +//import org.springframework.web.bind.annotation.*;
  13 +//import top.panll.assist.dto.UserSettings;
  14 +//import top.panll.assist.utils.PageInfo;
  15 +//
  16 +//import javax.servlet.http.HttpServletRequest;
  17 +//import javax.servlet.http.HttpServletResponse;
  18 +//import java.io.BufferedOutputStream;
  19 +//import java.io.File;
  20 +//import java.io.IOException;
  21 +//import java.io.RandomAccessFile;
  22 +//import java.nio.charset.StandardCharsets;
  23 +//import java.util.List;
  24 +//import java.util.Map;
  25 +//
  26 +//@Controller
  27 +//@RequestMapping("/download")
  28 +//public class DownloadController {
  29 +//
  30 +// private final static Logger logger = LoggerFactory.getLogger(DownloadController.class);
  31 +//
  32 +// @Autowired
  33 +// private UserSettings userSettings;
  34 +//
  35 +// /**
  36 +// * 获取app+stream列表
  37 +// *
  38 +// * @return
  39 +// */
  40 +// @GetMapping(value = "/**")
  41 +// @ResponseBody
  42 +// public void download(HttpServletRequest request, HttpServletResponse response) {
  43 +//
  44 +// String resourcePath = request.getServletPath();
  45 +// System.out.println(resourcePath);
  46 +// resourcePath = resourcePath.substring("/download".length() + 1, resourcePath.length());
  47 +// String record = userSettings.getRecord();
  48 +//// if (record.endsWith("/")) {
  49 +//// record = record.substring(0, record.length() - 1);
  50 +//// System.out.println(record);
  51 +//// }
  52 +// System.out.println(record + resourcePath);
  53 +// File file = new File(record + resourcePath);
  54 +// if (!file.exists()) {
  55 +// response.setStatus(HttpServletResponse.SC_NOT_FOUND);
  56 +// return;
51 57 // }
52   - System.out.println(record + resourcePath);
53   - File file = new File(record + resourcePath);
54   - if (!file.exists()) {
55   - response.setStatus(HttpServletResponse.SC_NOT_FOUND);
56   - return;
57   - }
58   -
59   - /**
60   - * 参考实现来自: CSDN 进修的CODER SpringBoot Java实现Http方式分片下载断点续传+实现H5大视频渐进式播放
61   - * https://blog.csdn.net/lovequanquqn/article/details/104562945
62   - */
63   - String range = request.getHeader("Range");
64   - logger.info("current request rang:" + range);
65   - //开始下载位置
66   - long startByte = 0;
67   - //结束下载位置
68   - long endByte = file.length() - 1;
69   - logger.info("文件开始位置:{},文件结束位置:{},文件总长度:{}", startByte, endByte, file.length());
70   -
71   - //有range的话
72   - if (range != null && range.contains("bytes=") && range.contains("-")) {
73   - range = range.substring(range.lastIndexOf("=") + 1).trim();
74   - String[] ranges = range.split("-");
75   - try {
76   - //判断range的类型
77   - if (ranges.length == 1) {
78   - // 类型一:bytes=-2343,
79   - if (range.startsWith("-")) {
80   - endByte = Long.parseLong(ranges[0]);
81   - }
82   - //类型二:bytes=2343-
83   - else if (range.endsWith("-")) {
84   - startByte = Long.parseLong(ranges[0]);
85   - }
86   - }
87   - //类型三:bytes=22-2343
88   - else if (ranges.length == 2) {
89   - startByte = Long.parseLong(ranges[0]);
90   - endByte = Long.parseLong(ranges[1]);
91   - }
92   -
93   - } catch (NumberFormatException e) {
94   - startByte = 0;
95   - endByte = file.length() - 1;
96   - logger.error("Range Occur Error,Message:{}", e.getLocalizedMessage());
97   - }
98   -
99   -
100   - }
101   -
102   - // 要下载的长度
103   - long contentLength = endByte - startByte + 1;
104   - // 文件名
105   - String fileName = file.getName();
106   - // 文件类型
107   - String contentType = request.getServletContext().getMimeType(fileName);
108   -
109   - // 解决下载文件时文件名乱码问题
110   - byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
111   - fileName = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);
112   -
113   - response.setHeader("Content-Type", contentType);
114   - response.setHeader("Content-Length", String.valueOf(contentLength));
115   - //inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名
116   - response.setHeader("Content-Disposition", "inline;filename=" + fileName);
117   - response.setContentType(contentType);
118   - if (range != null) {
119   - //各种响应头设置
120   - //支持断点续传,获取部分字节内容:
121   - response.setHeader("Accept-Ranges", "bytes");
122   - //http状态码要为206:表示获取部分内容
123   - response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
124   - // Content-Range,格式为:[要下载的开始位置]-[结束位置]/[文件总大小]
125   - response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());
126   - } else {
127   - response.setStatus(HttpServletResponse.SC_OK);
128   - }
129   -
130   -
131   - BufferedOutputStream outputStream = null;
132   - RandomAccessFile randomAccessFile = null;
133   - //已传送数据大小
134   - long transmitted = 0;
135   - try {
136   - randomAccessFile = new RandomAccessFile(file, "r");
137   -
138   - outputStream = new BufferedOutputStream(response.getOutputStream());
139   - byte[] buff = new byte[4096];
140   - int len = 0;
141   - randomAccessFile.seek(startByte);
142   - //warning:判断是否到了最后不足4096(buff的length)个byte这个逻辑((transmitted + len) <= contentLength)要放前面
143   - //不然会会先读取randomAccessFile,造成后面读取位置出错;
144   - while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
145   - outputStream.write(buff, 0, len);
146   - transmitted += len;
147   - }
148   - //处理不足buff.length部分
149   - if (transmitted < contentLength) {
150   - len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
151   - outputStream.write(buff, 0, len);
152   - transmitted += len;
153   - }
154   -
155   - outputStream.flush();
156   - response.flushBuffer();
157   - randomAccessFile.close();
158   - logger.info("下载完毕:" + startByte + "-" + endByte + ":" + transmitted);
159   - } catch (ClientAbortException e) {
160   - logger.warn("用户停止下载:" + startByte + "-" + endByte + ":" + transmitted);
161   - //捕获此异常表示拥护停止下载
162   - } catch (IOException e) {
163   - e.printStackTrace();
164   - logger.error("用户下载IO异常,Message:{}", e.getLocalizedMessage());
165   - } finally {
166   - try {
167   - if (randomAccessFile != null) {
168   - randomAccessFile.close();
169   - }
170   - } catch (IOException e) {
171   - e.printStackTrace();
172   - }
173   - }///end try
174   - }
175   -}
  58 +//
  59 +// /**
  60 +// * 参考实现来自: CSDN 进修的CODER SpringBoot Java实现Http方式分片下载断点续传+实现H5大视频渐进式播放
  61 +// * https://blog.csdn.net/lovequanquqn/article/details/104562945
  62 +// */
  63 +// String range = request.getHeader("Range");
  64 +// logger.info("current request rang:" + range);
  65 +// //开始下载位置
  66 +// long startByte = 0;
  67 +// //结束下载位置
  68 +// long endByte = file.length() - 1;
  69 +// logger.info("文件开始位置:{},文件结束位置:{},文件总长度:{}", startByte, endByte, file.length());
  70 +//
  71 +// //有range的话
  72 +// if (range != null && range.contains("bytes=") && range.contains("-")) {
  73 +// range = range.substring(range.lastIndexOf("=") + 1).trim();
  74 +// String[] ranges = range.split("-");
  75 +// try {
  76 +// //判断range的类型
  77 +// if (ranges.length == 1) {
  78 +// // 类型一:bytes=-2343,
  79 +// if (range.startsWith("-")) {
  80 +// endByte = Long.parseLong(ranges[0]);
  81 +// }
  82 +// //类型二:bytes=2343-
  83 +// else if (range.endsWith("-")) {
  84 +// startByte = Long.parseLong(ranges[0]);
  85 +// }
  86 +// }
  87 +// //类型三:bytes=22-2343
  88 +// else if (ranges.length == 2) {
  89 +// startByte = Long.parseLong(ranges[0]);
  90 +// endByte = Long.parseLong(ranges[1]);
  91 +// }
  92 +//
  93 +// } catch (NumberFormatException e) {
  94 +// startByte = 0;
  95 +// endByte = file.length() - 1;
  96 +// logger.error("Range Occur Error,Message:{}", e.getLocalizedMessage());
  97 +// }
  98 +//
  99 +//
  100 +// }
  101 +//
  102 +// // 要下载的长度
  103 +// long contentLength = endByte - startByte + 1;
  104 +// // 文件名
  105 +// String fileName = file.getName();
  106 +// // 文件类型
  107 +// String contentType = request.getServletContext().getMimeType(fileName);
  108 +//
  109 +// // 解决下载文件时文件名乱码问题
  110 +// byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
  111 +// fileName = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);
  112 +//
  113 +// response.setHeader("Content-Type", contentType);
  114 +// response.setHeader("Content-Length", String.valueOf(contentLength));
  115 +// //inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名
  116 +// response.setHeader("Content-Disposition", "inline;filename=" + fileName);
  117 +// response.setContentType(contentType);
  118 +// if (range != null) {
  119 +// //各种响应头设置
  120 +// //支持断点续传,获取部分字节内容:
  121 +// response.setHeader("Accept-Ranges", "bytes");
  122 +// //http状态码要为206:表示获取部分内容
  123 +// response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
  124 +// // Content-Range,格式为:[要下载的开始位置]-[结束位置]/[文件总大小]
  125 +// response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());
  126 +// } else {
  127 +// response.setStatus(HttpServletResponse.SC_OK);
  128 +// }
  129 +//
  130 +//
  131 +// BufferedOutputStream outputStream = null;
  132 +// RandomAccessFile randomAccessFile = null;
  133 +// //已传送数据大小
  134 +// long transmitted = 0;
  135 +// try {
  136 +// randomAccessFile = new RandomAccessFile(file, "r");
  137 +//
  138 +// outputStream = new BufferedOutputStream(response.getOutputStream());
  139 +// byte[] buff = new byte[4096];
  140 +// int len = 0;
  141 +// randomAccessFile.seek(startByte);
  142 +// //warning:判断是否到了最后不足4096(buff的length)个byte这个逻辑((transmitted + len) <= contentLength)要放前面
  143 +// //不然会会先读取randomAccessFile,造成后面读取位置出错;
  144 +// while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
  145 +// outputStream.write(buff, 0, len);
  146 +// transmitted += len;
  147 +// }
  148 +// //处理不足buff.length部分
  149 +// if (transmitted < contentLength) {
  150 +// len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
  151 +// outputStream.write(buff, 0, len);
  152 +// transmitted += len;
  153 +// }
  154 +//
  155 +// outputStream.flush();
  156 +// response.flushBuffer();
  157 +// randomAccessFile.close();
  158 +// logger.info("下载完毕:" + startByte + "-" + endByte + ":" + transmitted);
  159 +// } catch (ClientAbortException e) {
  160 +// logger.warn("用户停止下载:" + startByte + "-" + endByte + ":" + transmitted);
  161 +// //捕获此异常表示拥护停止下载
  162 +// } catch (IOException e) {
  163 +// e.printStackTrace();
  164 +// logger.error("用户下载IO异常,Message:{}", e.getLocalizedMessage());
  165 +// } finally {
  166 +// try {
  167 +// if (randomAccessFile != null) {
  168 +// randomAccessFile.close();
  169 +// }
  170 +// } catch (IOException e) {
  171 +// e.printStackTrace();
  172 +// }
  173 +// }///end try
  174 +// }
  175 +//}
... ...