diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java index b52db113d..892343f6d 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java @@ -2,12 +2,15 @@ package com.jsowell.common.util.file; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.ObjectMetadata; import com.jsowell.common.config.AliyunOssConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -62,4 +65,37 @@ public class AliyunOssUploadUtils { } return aliyunOssConfig.getUrl() + "/" + filePathName; } + + /** + * 上传到阿里云(车位相机用) + * @param compressedImageBytes + * @param fileName 文件名 (车位号 + 时间戳).jpg + * @return + */ + public static String upload2OSS(byte[] compressedImageBytes, String fileName) { + // 生成 OSSClient + OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); + + // 创建对象元数据,默认是可读的 + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(compressedImageBytes.length); // 设置内容长度 + + // 创建输入流 + InputStream inputStream = new ByteArrayInputStream(compressedImageBytes); + + //获取当前时间 + LocalDateTime currentDate = LocalDateTime.now(); + String dir_name = currentDate.getYear() + "/" + currentDate.getMonthValue() + "/" + currentDate.getDayOfMonth() + "/"; + + // 随机数 + String randomNumber = Long.toHexString(currentDate.toEpochSecond(ZoneOffset.UTC)) + "-"; + + // 文件路径名称 + String filePathName = aliyunOssConfig.getFilehost() + "/" + dir_name + randomNumber + fileName; + ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, inputStream, metadata); + + // 关闭 OSS 客户端 + ossClient.shutdown(); + return aliyunOssConfig.getUrl() + "/" + filePathName; + } } \ No newline at end of file diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/file/ImageUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/file/ImageUtils.java index d48583bb4..21468c208 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/file/ImageUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/file/ImageUtils.java @@ -7,9 +7,12 @@ import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.InputStream; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import java.awt.image.BufferedImage; +import java.io.*; import java.net.URL; import java.net.URLConnection; import java.util.Arrays; @@ -76,4 +79,39 @@ public class ImageUtils { IOUtils.closeQuietly(in); } } + + /** + * 图像压缩方法 + * @param originalImage 源图像 + * @param quality 压缩质量 + * @return + */ + public static BufferedImage compressImage(BufferedImage originalImage, double quality) { + BufferedImage compressedImage = null; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + try { + // 设置压缩参数 + ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next(); + ImageWriteParam param = writer.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionQuality((float) quality); + + // 压缩图像 + writer.setOutput(ImageIO.createImageOutputStream(outputStream)); + writer.write(null, new IIOImage(originalImage, null, null), param); + + // 读取压缩后的图像 + ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); + compressedImage = ImageIO.read(inputStream); + + // 关闭流 + outputStream.close(); + inputStream.close(); + writer.dispose(); + } catch (IOException e) { + e.printStackTrace(); + } + return compressedImage; + } } diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java index cfb4e3d7c..910d500f7 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java @@ -1,18 +1,32 @@ package com.jsowell.thirdparty.camera.service; -import cn.hutool.core.codec.Base64; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; -import com.jsowell.common.constant.CacheConstants; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.ObjectMetadata; +import com.jsowell.common.config.AliyunOssConfig; import com.jsowell.common.core.redis.RedisCache; -import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.file.AliyunOssUploadUtils; +import com.jsowell.common.util.file.ImageUtils; import com.jsowell.pile.domain.PileCameraInfo; import com.jsowell.pile.dto.camera.CameraIdentifyResultsDTO; import com.jsowell.pile.service.IPileCameraInfoService; import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Base64; +import javax.imageio.ImageIO; import java.util.List; @@ -24,6 +38,7 @@ import java.util.List; */ @Service public class CameraService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private RedisCache redisCache; @@ -89,10 +104,17 @@ public class CameraService { return false; } // Base64解密 - String plateNumber = Base64.decodeStr(plate.getPlate()); - String zoneName = Base64.decodeStr(parking.getZoneName()); + String plateNumber = cn.hutool.core.codec.Base64.decodeStr(plate.getPlate()); + String zoneName = cn.hutool.core.codec.Base64.decodeStr(parking.getZoneName()); for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) { + // 上传到阿里云OSS,获取图片上传成功后的地址 + String fileName = zoneName + "-" + System.currentTimeMillis() / 1000 + ".jpg"; + String url = saveImage(bgImg.getImage(), fileName); + if (StringUtils.isBlank(url)) { + logger.error("车位号:{} 图片上传失败", zoneName); + continue; + } PileCameraInfo pileCameraInfo = PileCameraInfo.builder() .deviceName(deviceInfo.getDevName()) .deviceIp(deviceInfo.getIp()) @@ -103,7 +125,7 @@ public class CameraService { .zoneName(zoneName) .color(plate.getColor()) .plateType(plate.getType()) - .image(bgImg.getImage()) + .image(url) .build(); // 插入数据库 @@ -114,34 +136,68 @@ public class CameraService { } + /** + * 保存图像 + * @param base64Image 图像的Base64编码 + * @param fileName 文件名 + * @return + */ + private String saveImage(String base64Image, String fileName) { + try { + // 将Base64编码的字符串解码为字节数组 + byte[] imageBytes = Base64.getDecoder().decode(base64Image); + + // 将字节数组转换为 BufferedImage + ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); + BufferedImage originalImage = ImageIO.read(inputStream); + + // 对图像进行压缩 + double quality = 0.5; // 压缩质量 + BufferedImage compressedImage = ImageUtils.compressImage(originalImage, quality); + + // 将压缩后的图片转换为字节数组 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageIO.write(compressedImage, "jpg", outputStream); + byte[] compressedImageBytes = outputStream.toByteArray(); + + // 上传图片到OSS + String url = AliyunOssUploadUtils.upload2OSS(compressedImageBytes, fileName); + if (StringUtils.isNotBlank(url)) { + return url; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } /** * 将车辆图片信息存入缓存 * @param jsonObject */ - private boolean saveCarPicture2Redis(JSONObject jsonObject, String parkingState) { - // 获取车牌号 - String plateNumber = jsonObject.getJSONObject("plate").getString("plate"); - if (StringUtils.isBlank(plateNumber)) { - return false; - } - // 获取背景图片 - JSONArray bgImgs = jsonObject.getJSONArray("bg_img"); - List bgImgList = bgImgs.toList(CameraIdentifyResultsDTO.BgImg.class); - if (CollectionUtils.isEmpty(bgImgList)) { - return false; - } - for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) { - String image = bgImg.getImage(); // 图片的 base64 编码 - // String key = bgImg.getKey(); // 索引id - // key: 前缀 + 车牌号 + 日期 + 入场/出场状态 - String redisKey = CacheConstants.CAMERA_IMAGE_BY_PLATE_NUMBER + plateNumber + "_" + DateUtils.getDate() + "_" + parkingState; - // 存入缓存 - // TODO 暂时永久保存 - redisCache.setCacheObject(redisKey, image); - } - return true; - } + // private boolean saveCarPicture2Redis(JSONObject jsonObject, String parkingState) { + // // 获取车牌号 + // String plateNumber = jsonObject.getJSONObject("plate").getString("plate"); + // if (StringUtils.isBlank(plateNumber)) { + // return false; + // } + // // 获取背景图片 + // JSONArray bgImgs = jsonObject.getJSONArray("bg_img"); + // List bgImgList = bgImgs.toList(CameraIdentifyResultsDTO.BgImg.class); + // if (CollectionUtils.isEmpty(bgImgList)) { + // return false; + // } + // for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) { + // String image = bgImg.getImage(); // 图片的 base64 编码 + // // String key = bgImg.getKey(); // 索引id + // // key: 前缀 + 车牌号 + 日期 + 入场/出场状态 + // String redisKey = CacheConstants.CAMERA_IMAGE_BY_PLATE_NUMBER + plateNumber + "_" + DateUtils.getDate() + "_" + parkingState; + // // 存入缓存 + // // 暂时永久保存 + // redisCache.setCacheObject(redisKey, image); + // } + // return true; + // } } diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java index 86104af10..a2035ea0a 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java @@ -120,7 +120,7 @@ public class ZDLServiceImpl implements ZDLService { // 组装中电联平台所需要的数据格式 ZDLStationInfo info = ZDLStationInfo.builder() .stationId(String.valueOf(dto.getStationId())) - .operatorId(operatorId) + .operatorId(Constants.OPERATORID_JIANG_SU) // .equipmentOwnerId(Constants.OPERATORID_JIANG_SU) .stationName(pileStationInfo.getStationName()) .countryCode(pileStationInfo.getCountryCode()) @@ -226,7 +226,7 @@ public class ZDLServiceImpl implements ZDLService { for (ThirdPartyStationInfoVO pileStationInfo : pageInfo.getList()) { ZDLStationInfo stationInfo = new ZDLStationInfo(); stationInfo.setStationId(String.valueOf(pileStationInfo.getId())); - stationInfo.setOperatorId(dto.getOperatorId()); // 组织机构代码 + stationInfo.setOperatorId(Constants.OPERATORID_JIANG_SU); // 组织机构代码 String organizationCode = pileStationInfo.getOrganizationCode(); if (StringUtils.isNotBlank(organizationCode) && organizationCode.length() == 18) { String equipmentOwnerId = StringUtils.substring(organizationCode, organizationCode.length() - 10, organizationCode.length() - 1); diff --git a/jsowell-ui/src/views/pile/camera/index.vue b/jsowell-ui/src/views/pile/camera/index.vue index 67f3b3e16..8af03b8cd 100644 --- a/jsowell-ui/src/views/pile/camera/index.vue +++ b/jsowell-ui/src/views/pile/camera/index.vue @@ -5,11 +5,11 @@ - - - - + + + + + @@ -17,19 +17,19 @@ - - - - - - + + + + + + + - - - + + + 搜索 重置 @@ -91,8 +91,9 @@