|
@@ -7,6 +7,7 @@ import com.ruoyi.advertiser25.mapper.ScreenMaterialMapper;
|
|
|
import com.ruoyi.advertiser25.service.IScreenMaterialService;
|
|
|
import com.ruoyi.common.config.RuoYiConfig;
|
|
|
import com.ruoyi.common.constant.Constants;
|
|
|
+import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.exception.file.FileException;
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
import com.ruoyi.common.utils.file.FileUtils;
|
|
@@ -15,6 +16,7 @@ import com.ruoyi.mcu25.constant.McuBeatIdentificationConstant25;
|
|
|
import com.ruoyi.mcu25.constant.McuBeatPackTypeConstant25;
|
|
|
import com.ruoyi.mcu25.domain.AdHeartBeatPackage25;
|
|
|
import com.ruoyi.mcu25.domain.HttpServerBean25;
|
|
|
+import com.ruoyi.mcu25.domain.HttpServerRedisDto;
|
|
|
import com.ruoyi.mcu25.util.CRC16ModbusUtil25;
|
|
|
import com.ruoyi.mcu25.util.DataTransitionUtil25;
|
|
|
import com.ruoyi.mcu25.util.ParseUtil25;
|
|
@@ -31,10 +33,9 @@ import java.net.URLEncoder;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.FileSystemException;
|
|
|
-import java.util.Base64;
|
|
|
-import java.util.Locale;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
|
* @author: jd
|
|
@@ -57,47 +58,82 @@ public class HttpServer25 {
|
|
|
@Resource
|
|
|
private ScreenMaterialMapper screenMaterialMapper;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private RedisCache redisCache;
|
|
|
+
|
|
|
@GetMapping("/{fileName}")
|
|
|
public void fileDownload(@PathVariable("fileName") String fileName, HttpServletResponse response, HttpServletRequest request) {
|
|
|
String ip = IpUtils.getIpAddr(request);
|
|
|
+ String range = request.getHeader("Range");
|
|
|
log.info("开始--设备请求下载!设备ip:{} ----------------------------------------------------------", ip);
|
|
|
- log.info("接收时间:{},接收参数:{},range:{}", DateUtil.now(), fileName, request.getHeader("Range"));
|
|
|
+ log.info("请求时间:{},请求参数:{},range:{}", DateUtil.now(), fileName, range);
|
|
|
try {
|
|
|
- // 禁止目录上跳级别
|
|
|
- if (StringUtils.contains(fileName, "..")) {
|
|
|
- throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
|
|
- }
|
|
|
- String[] file = fileName.split("\\.");
|
|
|
- String id = file[0];
|
|
|
- // 演示模式固定下载 65535.GSC
|
|
|
- if ("65535".equals(id)){
|
|
|
- Map demoPic = screenMaterialMapper.selectDemoPic();
|
|
|
- id = demoPic.get("oriId").toString();
|
|
|
- }
|
|
|
- Material25 material25 = materialService.selectMaterialById(Long.valueOf(id));
|
|
|
- if (material25 == null || StringUtils.isEmpty(material25.getConvertedFileUrl())){
|
|
|
- throw new Exception(StringUtils.format("系统未查询到文件:({}),下载失败。 ", fileName));
|
|
|
+ // 先尝试从redis读数据--读取不到在查询数据库时加入缓存。注意:如果图片支持根据id修改图片文件地址,则需要把redis对应文件清理掉
|
|
|
+ if (!readFromRedis(fileName, response, range)){
|
|
|
+ // 禁止目录上跳级别
|
|
|
+ if (StringUtils.contains(fileName, "..")) {
|
|
|
+ throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
|
|
+ }
|
|
|
+ String id = fileName.split("\\.")[0];
|
|
|
+ // 演示模式固定下载 65535.GSC
|
|
|
+ if ("65535".equals(id)){
|
|
|
+ id = screenMaterialMapper.selectDemoPic().get("oriId").toString();
|
|
|
+ }
|
|
|
+ Material25 material25 = materialService.selectMaterialById(Long.valueOf(id));
|
|
|
+ if (material25 == null || StringUtils.isEmpty(material25.getConvertedFileUrl())){
|
|
|
+ throw new Exception(StringUtils.format("系统未查询到文件:({}),下载失败。 ", fileName));
|
|
|
+ }
|
|
|
+ // 本地资源路径
|
|
|
+ String localPath = RuoYiConfig.getProfile();
|
|
|
+ // 数据库资源地址
|
|
|
+ String downloadPath = localPath + StringUtils.substringAfter(material25.getConvertedFileUrl(), Constants.RESOURCE_PREFIX);
|
|
|
+ // 下载名称
|
|
|
+ String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
|
|
+ FileUtils.setAttachmentResponseHeader(response, downloadName);
|
|
|
+ writeBytes(fileName, downloadPath, response, request);
|
|
|
}
|
|
|
- // 本地资源路径
|
|
|
- String localPath = RuoYiConfig.getProfile();
|
|
|
- // 数据库资源地址
|
|
|
- String downloadPath = localPath + StringUtils.substringAfter(material25.getConvertedFileUrl(), Constants.RESOURCE_PREFIX);
|
|
|
- // 下载名称
|
|
|
- String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
|
|
- FileUtils.setAttachmentResponseHeader(response, downloadName);
|
|
|
- writeBytes(downloadPath, response, request);
|
|
|
} catch (Exception e) {
|
|
|
log.error("下载文件失败", e);
|
|
|
log.error("结束--下载失败!设备ip:{}----------------------------------------------------------", ip);
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
log.info("结束--下载完成!设备ip:{}----------------------------------------------------------", ip);
|
|
|
}
|
|
|
|
|
|
+ private boolean readFromRedis( String fileName, HttpServletResponse response, String range) throws IOException {
|
|
|
+ String id = fileName.split("\\.")[0];
|
|
|
+ HttpServerRedisDto redisDto = redisCache.getCacheObject("PicServer:id_" + id + ":range" + range);
|
|
|
+ if (redisDto != null){
|
|
|
+ OutputStream os = null;
|
|
|
+ try {
|
|
|
+ FileUtils.setAttachmentResponseHeader(response, id);
|
|
|
+ response.setHeader("Access-Control-Allow-Origin","*");
|
|
|
+ response.setHeader("Accept-Ranges", "bytes");
|
|
|
+ if (StringUtils.isNotEmpty(range)){
|
|
|
+ response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
|
|
+ response.setHeader("Content-Range", redisDto.getContentRange());
|
|
|
+ }
|
|
|
+ response.setContentLength(redisDto.getContentLength());
|
|
|
+
|
|
|
+ os = response.getOutputStream();
|
|
|
+ for (int i = 0; i < redisDto.getData().size(); i++) {
|
|
|
+ os.write(redisDto.getData().get(i), 0, redisDto.getData().get(i).length);
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ throw e;
|
|
|
+ }finally {
|
|
|
+ os.close();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 说明:需要支持断点续传
|
|
|
*/
|
|
|
- public static void writeBytes(String filePath, HttpServletResponse response, HttpServletRequest request) throws IOException {
|
|
|
+ public void writeBytes(String filename, String filePath, HttpServletResponse response, HttpServletRequest request) throws IOException {
|
|
|
String range = request.getHeader("Range");
|
|
|
if (StringUtils.isNotEmpty(range) && range.contains(",")){
|
|
|
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
@@ -108,6 +144,8 @@ public class HttpServer25 {
|
|
|
response.setHeader("Access-Control-Allow-Origin","*");
|
|
|
response.setHeader("Accept-Ranges", "bytes");
|
|
|
|
|
|
+ HttpServerRedisDto redisDto = new HttpServerRedisDto();
|
|
|
+ redisDto.setId(filename.split("\\.")[0]);
|
|
|
OutputStream os = response.getOutputStream();
|
|
|
RandomAccessFile rf = null;
|
|
|
try {
|
|
@@ -116,6 +154,7 @@ public class HttpServer25 {
|
|
|
throw new FileNotFoundException(filePath);
|
|
|
}
|
|
|
long fileMaxSize = file.length() - 1;
|
|
|
+ redisDto.setMaxSize(fileMaxSize);
|
|
|
rf = new RandomAccessFile(file, "r");
|
|
|
int downLength = 0;
|
|
|
// 是否断点续传
|
|
@@ -123,7 +162,9 @@ public class HttpServer25 {
|
|
|
// 续传返回206
|
|
|
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
|
|
// 读取范围
|
|
|
- response.setHeader("Content-Range", range.replace("=", " ") + "/" + fileMaxSize);
|
|
|
+ String contentRange = range.replace("=", " ") + "/" + fileMaxSize;
|
|
|
+ redisDto.setContentRange(contentRange);
|
|
|
+ response.setHeader("Content-Range", contentRange);
|
|
|
String[] readRange = range.replace("bytes=","").trim().split("-");
|
|
|
Long start = 0L;
|
|
|
Long end = 0L;
|
|
@@ -145,13 +186,19 @@ public class HttpServer25 {
|
|
|
if (downLength == 0){
|
|
|
downLength = (int) fileMaxSize + 1;
|
|
|
}
|
|
|
+ redisDto.setContentLength(downLength);
|
|
|
response.setContentLength(downLength);
|
|
|
+ List<byte[]> list = new ArrayList<>();
|
|
|
byte[] b = new byte[1024];
|
|
|
int length;
|
|
|
while (downLength > 0 && (length = rf.read(b)) > 0) {
|
|
|
+ list.add(Arrays.copyOf(b, length>downLength? downLength :length));
|
|
|
os.write(b, 0, length>downLength? downLength :length);
|
|
|
downLength -= length;
|
|
|
}
|
|
|
+ redisDto.setData(list);
|
|
|
+ // 一般认为24小时内图片肯定可以下载完
|
|
|
+ redisCache.setCacheObject("PicServer:id_" + redisDto.getId() + ":range" + range, redisDto, 24, TimeUnit.HOURS);
|
|
|
} catch (IOException e) {
|
|
|
throw e;
|
|
|
} finally {
|