From 9958bc1501d0daee954d9bba383475e55e24ebab Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Thu, 14 May 2026 08:18:07 +0800
Subject: [PATCH] 优化

---
 ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java |  223 +++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 157 insertions(+), 66 deletions(-)

diff --git a/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java b/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
index 6cfaad6..e4e7991 100644
--- a/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
+++ b/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
@@ -5,6 +5,7 @@
 import com.ard.common.core.exception.ServiceException;
 import com.ard.common.core.exception.device.CameraSDKException;
 import com.ard.common.core.utils.StringUtils;
+import com.ard.common.core.utils.file.FileMultipartFile;
 import com.ard.common.core.utils.file.FileUtils;
 import com.ard.common.core.utils.file.MimeTypeUtils;
 import com.ard.common.redis.service.RedisService;
@@ -30,7 +31,6 @@
 import com.ard.work.sdk.model.PtzScope;
 import com.ard.work.sdk.service.CameraSDK;
 import com.ard.work.utils.FFmpegUtils;
-import com.ard.work.utils.file.MultipartFileUtil;
 import com.ard.work.utils.gis.GisUtil;
 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
@@ -1561,6 +1561,7 @@
         String type = cmd.getType() == null ? "other" : cmd.getType();
         String bucketName = cmd.getBucketName() == null ? "pic" : cmd.getBucketName();
         int userId = cmd.getLoginId().intValue();
+
         //图片信息
         NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
         //设置图片分辨率
@@ -1570,8 +1571,9 @@
         IntByReference a = new IntByReference();
         //设置图片大小
         ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
-        // 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
+        // 抓图到内存
         boolean bool = hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, chanNo, jpeg, jpegBuffer, 1024 * 1024, a);
+
         if (!bool) {
             int errorCode = hCNetSDK.NET_DVR_GetLastError();
             String errorDesc = SdkErrorCodeEnum.getDescByCode(errorCode);
@@ -1579,19 +1581,46 @@
             log.warn(errorMsg);
             return "";
         }
+
         log.debug("hikSdk(抓图)-结果状态值(0表示成功):{}", hCNetSDK.NET_DVR_GetLastError());
-        byte[] array = jpegBuffer.array();
-        //存储到minio
-        String objectName = cameraId + "_" + chanNo + ".jpeg";
-        InputStream inputStream = new ByteArrayInputStream(array);
-        String url = "";
-        MultipartFile multipartFile = MultipartFileUtil.inputStreamToMultipartFile(inputStream, objectName,
-                MimeTypeUtils.IMAGE_JPEG);
-        R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
-        if (sysFileR.getCode() == R.SUCCESS) {
-            url = sysFileR.getData().getUrl();
-            log.debug("上传文件成功:{}", url);
+
+        // 获取实际图片数据
+        int actualLength = a.getValue();
+        byte[] imageBytes;
+        if (actualLength > 0 && actualLength < 1024 * 1024) {
+            imageBytes = new byte[actualLength];
+            System.arraycopy(jpegBuffer.array(), 0, imageBytes, 0, actualLength);
+        } else {
+            imageBytes = jpegBuffer.array();
         }
+
+        // 存储到minio
+        String objectName = cameraId + "_" + chanNo + ".jpeg";
+        String url = "";
+        File tempFile = null;
+
+        try {
+            // 创建临时文件
+            tempFile = File.createTempFile("snap_", ".jpeg");
+            java.nio.file.Files.write(tempFile.toPath(), imageBytes);
+
+            // 使用 FileMultipartFile 转换
+            MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.IMAGE_JPEG);
+
+            R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+            if (sysFileR.getCode() == R.SUCCESS) {
+                url = sysFileR.getData().getUrl();
+                log.debug("上传文件成功:{}", url);
+            }
+        } catch (Exception e) {
+            log.error("上传失败", e);
+        } finally {
+            // 删除临时文件
+            if (tempFile != null && tempFile.exists()) {
+                tempFile.delete();
+            }
+        }
+
         return url;
     }
 
@@ -1602,6 +1631,7 @@
         Integer chanNo = cmd.getChanNo();
         String type = cmd.getType() == null ? "other" : cmd.getType();
         Integer userId = cmd.getLoginId().intValue();
+
         //图片信息
         NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
         //设置图片分辨率
@@ -1613,6 +1643,7 @@
         ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
         // 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
         boolean bool = hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, chanNo, jpeg, jpegBuffer, 1024 * 1024, a);
+
         if (!bool) {
             int errorCode = hCNetSDK.NET_DVR_GetLastError();
             String errorDesc = SdkErrorCodeEnum.getDescByCode(errorCode);
@@ -1620,22 +1651,50 @@
             log.warn(errorMsg);
             return "";
         }
-        byte[] array = jpegBuffer.array();
-        InputStream inputStream = new ByteArrayInputStream(array);
-        String url = "";
-        MultipartFile multipartFile = MultipartFileUtil.inputStreamToMultipartFile(inputStream, objectName,
-                MimeTypeUtils.IMAGE_JPEG);
-        R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
-        if (sysFileR.getCode() == R.SUCCESS) {
-            url = sysFileR.getData().getUrl();
-            log.debug("上传文件成功:{}", url);
+
+        // 获取实际图片数据(只复制有效长度)
+        int actualLength = a.getValue();
+        byte[] imageBytes;
+        if (actualLength > 0 && actualLength < 1024 * 1024) {
+            imageBytes = new byte[actualLength];
+            System.arraycopy(jpegBuffer.array(), 0, imageBytes, 0, actualLength);
+        } else {
+            imageBytes = jpegBuffer.array();
         }
+
+        String url = "";
+        File tempFile = null;
+
+        try {
+            // 创建临时文件
+            tempFile = File.createTempFile("snap_", ".jpeg");
+            java.nio.file.Files.write(tempFile.toPath(), imageBytes);
+
+            // 使用 FileMultipartFile 转换
+            MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.IMAGE_JPEG);
+
+            R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+            if (sysFileR.getCode() == R.SUCCESS) {
+                url = sysFileR.getData().getUrl();
+                log.debug("上传文件成功:{}", url);
+            }
+        } catch (Exception e) {
+            log.error("上传失败", e);
+        } finally {
+            if (tempFile != null && tempFile.exists()) {
+                tempFile.delete();
+            }
+        }
+
         return url;
     }
 
     //短时录像
     @Override
     public String record(CameraCmd cmd) {
+        String url = "";
+        File tempFile = null;
+
         try {
             String cameraId = cmd.getCameraId();
             Integer chanNo = cmd.getChanNo();
@@ -1644,29 +1703,32 @@
             String path = FileUtils.createFile(tempDir + "/record/" + name + ".mp4");
             boolean enable = cmd.isEnable();
             Integer userId = cmd.getLoginId().intValue();
+
             //强制I帧结构体对象
-            NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME();   //新建结构体对象
+            NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME();
             netDvrIFrame.read();
-            netDvrIFrame.dwChannel = chanNo;//因为上文代码中设置了通道号,按照上文中的设置
+            netDvrIFrame.dwChannel = chanNo;
             netDvrIFrame.byStreamType = 0;
             netDvrIFrame.dwSize = netDvrIFrame.size();
             netDvrIFrame.write();
+
             if (!hCNetSDK.NET_DVR_RemoteControl(userId, 3402, netDvrIFrame.getPointer(), netDvrIFrame.dwSize)) {
                 log.error("强制I帧 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
             }
+
             //预览参数
             NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
             previewInfo.read();
             previewInfo.lChannel = chanNo;
-            previewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推
-            previewInfo.dwLinkMode = 0;//连接方式:0-TCP方式,1-UDP方式,2-多播方式,3-RTP方式,4-RTP/RTSP,5-RTP/HTTP,6-HRUDP(可靠传输),7
-            // -RTSP/HTTPS,8-NPQ
-            previewInfo.hPlayWnd = null;//播放窗口的句柄,为NULL表示不解码显示。
-            previewInfo.bBlocked = 0;//0- 非阻塞取流,1-阻塞取流
-            previewInfo.byNPQMode = 0;//NPQ模式:0-直连模式,1-过流媒体模式
+            previewInfo.dwStreamType = 0;
+            previewInfo.dwLinkMode = 0;
+            previewInfo.hPlayWnd = null;
+            previewInfo.bBlocked = 0;
+            previewInfo.byNPQMode = 0;
             previewInfo.write();
-            String url = "";
+
             if (enable) {
+                // 开始录像
                 if (!GlobalVariable.previewMap.containsKey(name)) {
                     int lRealHandle = hCNetSDK.NET_DVR_RealPlay_V40(userId, previewInfo, null, null);
                     if (lRealHandle == -1) {
@@ -1676,6 +1738,7 @@
                     log.debug("取流成功");
                     GlobalVariable.previewMap.put(name, lRealHandle);
                 }
+
                 if (!hCNetSDK.NET_DVR_SaveRealData_V30((int) GlobalVariable.previewMap.get(name), 2, path)) {
                     log.error("保存视频文件到临时文件夹失败 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
                     return "";
@@ -1683,24 +1746,40 @@
                 log.debug("录像开始");
 
             } else {
+                // 停止录像
                 if (GlobalVariable.previewMap.containsKey(name)) {
                     Integer lRealHandle = (Integer) GlobalVariable.previewMap.get(name);
                     hCNetSDK.NET_DVR_StopRealPlay(lRealHandle);
                     GlobalVariable.previewMap.remove(name);
                 }
                 log.debug("录像停止");
-                //存入minio
+
+                // 检查录像文件是否存在
+                File videoFile = new File(path);
+                if (!videoFile.exists() || videoFile.length() == 0) {
+                    log.error("录像文件不存在或为空: {}", path);
+                    return "";
+                }
+
+                // 存入minio - 使用 FileMultipartFile
                 String bucketName = "record";
-                String objectName = cameraId + "_" + chanNo;
-                MultipartFile multipartFile = MultipartFileUtil.filePathToMultipartFile(path, objectName,
-                        MimeTypeUtils.VIDEO_MP4);
+                String objectName = cameraId + "_" + chanNo + ".mp4";
+
+                // 创建临时文件对象(实际上 path 已经是文件路径)
+                tempFile = new File(path);
+
+                // 使用 FileMultipartFile 转换
+                MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.VIDEO_MP4);
+
                 R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName);
                 if (sysFileR.getCode() == R.SUCCESS) {
                     url = sysFileR.getData().getUrl();
                     log.debug("上传文件成功:{}", url);
                 }
             }
+
             return url;
+
         } catch (Exception ex) {
             log.error("录像异常:{}", ex.getMessage());
             return "";
@@ -1763,69 +1842,81 @@
             return false;
         }
     }
-
     @Override
     public String recordStop(CameraCmd cmd) {
         String url = "";
+        File videoFile = null;
+        File transcodeFile = null;
+
         try {
             String cameraId = cmd.getCameraId();
             Integer chanNo = cmd.getChanNo();
             String name = cameraId + "_" + chanNo;
             // 本地临时录像地址
             String path = FileUtils.createFile(tempDir + "/record/" + name + ".mp4");
-            Integer userId = cmd.getLoginId().intValue();
-            //region 强制I帧
-            NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME();   //新建结构体对象
-            netDvrIFrame.read();
-            netDvrIFrame.dwChannel = chanNo;//因为上文代码中设置了通道号,按照上文中的设置
-            netDvrIFrame.byStreamType = 0;
-            netDvrIFrame.dwSize = netDvrIFrame.size();
-            netDvrIFrame.write();
-            if (!hCNetSDK.NET_DVR_RemoteControl(userId, 3402, netDvrIFrame.getPointer(), netDvrIFrame.dwSize)) {
-                log.error("强制I帧 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
-            }
-            //endregion
-            //region 预览参数
-            NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
-            previewInfo.read();
-            previewInfo.lChannel = chanNo;
-            previewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推
-            previewInfo.dwLinkMode = 0;//连接方式:0-TCP方式,1-UDP方式,2-多播方式,3-RTP方式,4-RTP/RTSP,5-RTP/HTTP,6-HRUDP(可靠传输),7
-            // -RTSP/HTTPS,8-NPQ
-            previewInfo.hPlayWnd = null;//播放窗口的句柄,为NULL表示不解码显示。
-            previewInfo.bBlocked = 0;//0- 非阻塞取流,1-阻塞取流
-            previewInfo.byNPQMode = 0;//NPQ模式:0-直连模式,1-过流媒体模式
-            previewInfo.write();
-            //endregion
+
+            // 停止录像
             if (GlobalVariable.previewMap.containsKey(name)) {
                 Integer lRealHandle = (Integer) GlobalVariable.previewMap.get(name);
                 hCNetSDK.NET_DVR_StopRealPlay(lRealHandle);
                 GlobalVariable.previewMap.remove(name);
             }
             log.debug("录像停止");
-            //ffmpeg转码
+
+            // 检查原录像文件是否存在
+            videoFile = new File(path);
+            if (!videoFile.exists() || videoFile.length() == 0) {
+                log.error("录像文件不存在或为空: {}", path);
+                return "";
+            }
+
+            // ffmpeg转码
             StopWatch watchStop = new StopWatch();
             watchStop.start();
             String newpath = FileUtils.createFile(tempDir + "/record/" + name + "_c.mp4");
+            transcodeFile = new File(newpath);
             FFmpegUtils.transcodeToMP4(path, newpath);
             watchStop.stop();
             log.warn("转码耗时:{}", watchStop.getTotalTimeMillis());
-            //存入minio
+
+            // 检查转码后的文件是否存在
+            if (!transcodeFile.exists() || transcodeFile.length() == 0) {
+                log.error("转码文件不存在或为空: {}", newpath);
+                return "";
+            }
+
+            // 存入minio - 使用 FileMultipartFile
             String bucketName = "record";
-            String objectName = cameraId + "_" + chanNo;
+            String objectName = cameraId + "_" + chanNo + ".mp4";
             String type = cmd.getType();
-            MultipartFile multipartFile = MultipartFileUtil.filePathToMultipartFile(newpath, objectName,
-                    MimeTypeUtils.VIDEO_MP4);
+
+            MultipartFile multipartFile = new FileMultipartFile(transcodeFile, objectName, MimeTypeUtils.VIDEO_MP4);
             R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+
             if (sysFileR.getCode() == R.SUCCESS) {
                 url = sysFileR.getData().getUrl();
                 log.info("上传文件成功:{}", url);
             }
 
             return url;
+
         } catch (Exception ex) {
             log.error("录像异常:{}", ex.getMessage());
             return "";
+        } finally {
+            // 清理临时文件
+            try {
+                if (videoFile != null && videoFile.exists()) {
+                    videoFile.delete();
+                    log.debug("删除原录像文件: {}", videoFile.getPath());
+                }
+                if (transcodeFile != null && transcodeFile.exists()) {
+                    transcodeFile.delete();
+                    log.debug("删除转码文件: {}", transcodeFile.getPath());
+                }
+            } catch (Exception e) {
+                log.warn("删除临时文件失败", e);
+            }
         }
     }
 
@@ -1891,7 +1982,7 @@
                         camera.getRtspPort(),
                         channel.getChanNo()
                 );
-                channel.setRtspUrl(rtspUrl);
+                channel.setLiveAddress(rtspUrl);
                 channelList.add(channel);
             }
         }

--
Gitblit v1.9.3