Pārlūkot izejas kodu

图片下载修改

wangwx 1 gadu atpakaļ
vecāks
revīzija
ebdcee790f

+ 19 - 0
ruoyi-system25/src/main/java/com/ruoyi/mcu25/domain/HttpServerRedisDto.java

@@ -0,0 +1,19 @@
+package com.ruoyi.mcu25.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author: jd
+ * @Description:
+ * @create: 2023/7/7
+ */
+@Data
+public class HttpServerRedisDto {
+    private String id;
+    private List<byte[]> data;
+    private Long maxSize;
+    private String contentRange;
+    private Integer contentLength;
+}

+ 1 - 0
ruoyi-system25/src/main/java/com/ruoyi/mcu25/server/DealChannel25.java

@@ -151,6 +151,7 @@ public class DealChannel25 {
         if (beatPack.getPackageType() == McuBeatPackTypeConstant25.UP_BEAT_PACKAGE_TYPE) {
             // 处理心跳包-工作状态 0:默认模式 1:投屏模式
             int workType = beatPack.getDeviceInfo().getDevWorkStatus();
+            log.info("工作模式:" + workType);
             if (workType == 0){
                 responseBytes = dealServer25.upBeatReply(beatPack);
             }

+ 75 - 28
ruoyi-system25/src/main/java/com/ruoyi/mcu25/server/HttpServer25.java

@@ -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 {