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 +//}