mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-05-17 16:28:41 +08:00
新增 车位相机图片上传到OSS服务器
This commit is contained in:
@@ -2,12 +2,15 @@ package com.jsowell.common.util.file;
|
|||||||
|
|
||||||
import com.aliyun.oss.OSS;
|
import com.aliyun.oss.OSS;
|
||||||
import com.aliyun.oss.OSSClientBuilder;
|
import com.aliyun.oss.OSSClientBuilder;
|
||||||
|
import com.aliyun.oss.model.ObjectMetadata;
|
||||||
import com.jsowell.common.config.AliyunOssConfig;
|
import com.jsowell.common.config.AliyunOssConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
@@ -62,4 +65,37 @@ public class AliyunOssUploadUtils {
|
|||||||
}
|
}
|
||||||
return aliyunOssConfig.getUrl() + "/" + filePathName;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,9 +7,12 @@ import org.apache.poi.util.IOUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import javax.imageio.IIOImage;
|
||||||
import java.io.FileInputStream;
|
import javax.imageio.ImageIO;
|
||||||
import java.io.InputStream;
|
import javax.imageio.ImageWriteParam;
|
||||||
|
import javax.imageio.ImageWriter;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -76,4 +79,39 @@ public class ImageUtils {
|
|||||||
IOUtils.closeQuietly(in);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,32 @@
|
|||||||
package com.jsowell.thirdparty.camera.service;
|
package com.jsowell.thirdparty.camera.service;
|
||||||
|
|
||||||
import cn.hutool.core.codec.Base64;
|
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
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.core.redis.RedisCache;
|
||||||
import com.jsowell.common.util.DateUtils;
|
|
||||||
import com.jsowell.common.util.StringUtils;
|
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.domain.PileCameraInfo;
|
||||||
import com.jsowell.pile.dto.camera.CameraIdentifyResultsDTO;
|
import com.jsowell.pile.dto.camera.CameraIdentifyResultsDTO;
|
||||||
import com.jsowell.pile.service.IPileCameraInfoService;
|
import com.jsowell.pile.service.IPileCameraInfoService;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -24,6 +38,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class CameraService {
|
public class CameraService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
@@ -89,10 +104,17 @@ public class CameraService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Base64解密
|
// Base64解密
|
||||||
String plateNumber = Base64.decodeStr(plate.getPlate());
|
String plateNumber = cn.hutool.core.codec.Base64.decodeStr(plate.getPlate());
|
||||||
String zoneName = Base64.decodeStr(parking.getZoneName());
|
String zoneName = cn.hutool.core.codec.Base64.decodeStr(parking.getZoneName());
|
||||||
|
|
||||||
for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) {
|
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()
|
PileCameraInfo pileCameraInfo = PileCameraInfo.builder()
|
||||||
.deviceName(deviceInfo.getDevName())
|
.deviceName(deviceInfo.getDevName())
|
||||||
.deviceIp(deviceInfo.getIp())
|
.deviceIp(deviceInfo.getIp())
|
||||||
@@ -103,7 +125,7 @@ public class CameraService {
|
|||||||
.zoneName(zoneName)
|
.zoneName(zoneName)
|
||||||
.color(plate.getColor())
|
.color(plate.getColor())
|
||||||
.plateType(plate.getType())
|
.plateType(plate.getType())
|
||||||
.image(bgImg.getImage())
|
.image(url)
|
||||||
|
|
||||||
.build();
|
.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
|
* @param jsonObject
|
||||||
*/
|
*/
|
||||||
private boolean saveCarPicture2Redis(JSONObject jsonObject, String parkingState) {
|
// private boolean saveCarPicture2Redis(JSONObject jsonObject, String parkingState) {
|
||||||
// 获取车牌号
|
// // 获取车牌号
|
||||||
String plateNumber = jsonObject.getJSONObject("plate").getString("plate");
|
// String plateNumber = jsonObject.getJSONObject("plate").getString("plate");
|
||||||
if (StringUtils.isBlank(plateNumber)) {
|
// if (StringUtils.isBlank(plateNumber)) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
// 获取背景图片
|
// // 获取背景图片
|
||||||
JSONArray bgImgs = jsonObject.getJSONArray("bg_img");
|
// JSONArray bgImgs = jsonObject.getJSONArray("bg_img");
|
||||||
List<CameraIdentifyResultsDTO.BgImg> bgImgList = bgImgs.toList(CameraIdentifyResultsDTO.BgImg.class);
|
// List<CameraIdentifyResultsDTO.BgImg> bgImgList = bgImgs.toList(CameraIdentifyResultsDTO.BgImg.class);
|
||||||
if (CollectionUtils.isEmpty(bgImgList)) {
|
// if (CollectionUtils.isEmpty(bgImgList)) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) {
|
// for (CameraIdentifyResultsDTO.BgImg bgImg : bgImgList) {
|
||||||
String image = bgImg.getImage(); // 图片的 base64 编码
|
// String image = bgImg.getImage(); // 图片的 base64 编码
|
||||||
// String key = bgImg.getKey(); // 索引id
|
// // String key = bgImg.getKey(); // 索引id
|
||||||
// key: 前缀 + 车牌号 + 日期 + 入场/出场状态
|
// // key: 前缀 + 车牌号 + 日期 + 入场/出场状态
|
||||||
String redisKey = CacheConstants.CAMERA_IMAGE_BY_PLATE_NUMBER + plateNumber + "_" + DateUtils.getDate() + "_" + parkingState;
|
// String redisKey = CacheConstants.CAMERA_IMAGE_BY_PLATE_NUMBER + plateNumber + "_" + DateUtils.getDate() + "_" + parkingState;
|
||||||
// 存入缓存
|
// // 存入缓存
|
||||||
// TODO 暂时永久保存
|
// // 暂时永久保存
|
||||||
redisCache.setCacheObject(redisKey, image);
|
// redisCache.setCacheObject(redisKey, image);
|
||||||
}
|
// }
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable
|
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable
|
||||||
@keyup.enter.native="handleQuery" />
|
@keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备IP地址" prop="deviceIp">
|
<!-- <el-form-item label="设备IP地址" prop="deviceIp">-->
|
||||||
<el-input v-model="queryParams.deviceIp" placeholder="请输入设备IP地址" clearable
|
<!-- <el-input v-model="queryParams.deviceIp" placeholder="请输入设备IP地址" clearable-->
|
||||||
@keyup.enter.native="handleQuery" />
|
<!-- @keyup.enter.native="handleQuery" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item label="设备sn号" prop="deviceSn">
|
<el-form-item label="设备sn号" prop="deviceSn" label-width="75px">
|
||||||
<el-input v-model="queryParams.deviceSn" placeholder="请输入设备sn号" clearable
|
<el-input v-model="queryParams.deviceSn" placeholder="请输入设备sn号" clearable
|
||||||
@keyup.enter.native="handleQuery" />
|
@keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -17,19 +17,19 @@
|
|||||||
<el-input v-model="queryParams.plateNumber" placeholder="请输入车牌号" clearable
|
<el-input v-model="queryParams.plateNumber" placeholder="请输入车牌号" clearable
|
||||||
@keyup.enter.native="handleQuery" />
|
@keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="车位状态" prop="parkingState">
|
<!-- <el-form-item label="车位状态" prop="parkingState">-->
|
||||||
<el-input v-model="queryParams.parkingState" placeholder="请输入车位状态" clearable
|
<!-- <el-input v-model="queryParams.parkingState" placeholder="请输入车位状态" clearable-->
|
||||||
@keyup.enter.native="handleQuery" />
|
<!-- @keyup.enter.native="handleQuery" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item label="车位id" prop="zoneId">
|
<!-- <el-form-item label="车位id" prop="zoneId">-->
|
||||||
<el-input v-model="queryParams.zoneId" placeholder="请输入车位id" clearable @keyup.enter.native="handleQuery" />
|
<!-- <el-input v-model="queryParams.zoneId" placeholder="请输入车位id" clearable @keyup.enter.native="handleQuery" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item label="车位名" prop="zoneName">
|
<el-form-item label="车位名" prop="zoneName">
|
||||||
<el-input v-model="queryParams.zoneName" placeholder="请输入车位名" clearable @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.zoneName" placeholder="请输入车位名" clearable @keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="车牌颜色" prop="color">
|
<!-- <el-form-item label="车牌颜色" prop="color">-->
|
||||||
<el-input v-model="queryParams.color" placeholder="请输入车牌颜色" clearable @keyup.enter.native="handleQuery" />
|
<!-- <el-input v-model="queryParams.color" placeholder="请输入车牌颜色" clearable @keyup.enter.native="handleQuery" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
|||||||
Reference in New Issue
Block a user