被检设备上传图片功能
This commit is contained in:
@@ -23,6 +23,7 @@ import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@@ -69,10 +70,10 @@ public class PqDevController extends BaseController {
|
||||
}
|
||||
|
||||
@OperateInfo(operateType = OperateType.ADD)
|
||||
@PostMapping("/add")
|
||||
@PostMapping(value = "/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@ApiOperation("新增被检设备")
|
||||
@ApiImplicitParam(name = "pqDevParam", value = "被检设备", required = true)
|
||||
public HttpResult<Boolean> add(@RequestBody @Validated PqDevParam pqDevParam) {
|
||||
public HttpResult<Boolean> add(@ModelAttribute @Validated PqDevParam pqDevParam) {
|
||||
String methodDescribe = getMethodDescribe("add");
|
||||
LogUtil.njcnDebug(log, "{},新增数据为:{}", methodDescribe, pqDevParam);
|
||||
boolean result = pqDevService.addPqDev(pqDevParam);
|
||||
@@ -84,10 +85,10 @@ public class PqDevController extends BaseController {
|
||||
}
|
||||
|
||||
@OperateInfo(operateType = OperateType.UPDATE)
|
||||
@PostMapping("/update")
|
||||
@PostMapping(value = "/update", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@ApiOperation("修改被检设备")
|
||||
@ApiImplicitParam(name = "updateParam", value = "被检设备", required = true)
|
||||
public HttpResult<Boolean> update(@RequestBody @Validated PqDevParam.UpdateParam updateParam) {
|
||||
public HttpResult<Boolean> update(@ModelAttribute @Validated PqDevParam.UpdateParam updateParam) {
|
||||
String methodDescribe = getMethodDescribe("update");
|
||||
LogUtil.njcnDebug(log, "{},修改数据为:{}", methodDescribe, updateParam);
|
||||
boolean result = pqDevService.updatePqDev(updateParam);
|
||||
@@ -98,6 +99,14 @@ public class PqDevController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.DOWNLOAD)
|
||||
@GetMapping("/image/download")
|
||||
@ApiOperation("下载设备图片")
|
||||
@ApiImplicitParam(name = "id", value = "被检设备id", required = true)
|
||||
public void downloadImage(@RequestParam("id") String id, HttpServletResponse response) {
|
||||
pqDevService.downloadImage(id, response);
|
||||
}
|
||||
|
||||
@OperateInfo(operateType = OperateType.DELETE)
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation("删除被检设备")
|
||||
|
||||
@@ -86,8 +86,45 @@
|
||||
WHERE id = #{planId}
|
||||
</select>
|
||||
|
||||
<sql id="DevColumnsNoImage">
|
||||
dev.Id,
|
||||
dev.Name,
|
||||
dev.Pattern,
|
||||
dev.Dev_Type,
|
||||
dev.Manufacturer,
|
||||
dev.Create_Date,
|
||||
dev.Create_Id,
|
||||
dev.Hardware_Version,
|
||||
dev.Software_Version,
|
||||
dev.Protocol,
|
||||
dev.IP,
|
||||
dev.Port,
|
||||
dev.Encryption_Flag,
|
||||
dev.Series,
|
||||
dev.Dev_Key,
|
||||
dev.Sample_Id,
|
||||
dev.Arrived_Date,
|
||||
dev.City_Name,
|
||||
dev.Gd_Name,
|
||||
dev.Sub_Name,
|
||||
dev.Report_Path,
|
||||
dev.Plan_Id,
|
||||
dev.Factor_Flag,
|
||||
dev.Preinvestment_Plan,
|
||||
dev.Delegate,
|
||||
dev.Inspect_Channel,
|
||||
dev.Inspect_Date,
|
||||
dev.Harm_Sys_Id,
|
||||
dev.Import_Flag,
|
||||
dev.State,
|
||||
dev.Create_By,
|
||||
dev.Create_Time,
|
||||
dev.Update_By,
|
||||
dev.Update_Time
|
||||
</sql>
|
||||
|
||||
<select id="selectByQueryParam" resultType="com.njcn.gather.device.pojo.vo.PqDevVO">
|
||||
SELECT dev.*,dev_sub.* FROM pq_dev dev
|
||||
SELECT <include refid="DevColumnsNoImage"/>, dev_sub.* FROM pq_dev dev
|
||||
left JOIN pq_dev_sub dev_sub ON dev.Id = dev_sub.Dev_Id
|
||||
<where>
|
||||
dev.state = 1
|
||||
@@ -124,7 +161,7 @@
|
||||
</select>
|
||||
|
||||
<select id="listByDevIds" resultType="com.njcn.gather.device.pojo.vo.PqDevVO">
|
||||
SELECT dev.*, dev_sub.*
|
||||
SELECT <include refid="DevColumnsNoImage"/>, dev_sub.*
|
||||
FROM pq_dev dev
|
||||
left JOIN pq_dev_sub dev_sub ON dev.Id = dev_sub.Dev_Id
|
||||
WHERE dev.state = 1
|
||||
|
||||
@@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.*;
|
||||
@@ -136,6 +137,9 @@ public class PqDevParam {
|
||||
@ApiModelProperty("是否为导入设备")
|
||||
private Integer importFlag;
|
||||
|
||||
@ApiModelProperty("设备图片")
|
||||
private MultipartFile image;
|
||||
|
||||
/**
|
||||
* 更新操作实体
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.njcn.gather.device.pojo.po;
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
@@ -184,6 +185,9 @@ public class PqDev extends BaseEntity implements Serializable {
|
||||
*/
|
||||
private Integer importFlag;
|
||||
|
||||
@JsonIgnore
|
||||
private byte[] image;
|
||||
|
||||
/**
|
||||
* 状态:0-删除 1-正常
|
||||
*/
|
||||
|
||||
@@ -122,4 +122,10 @@ public class PqDevVO extends PqDev {
|
||||
* 检测点结果
|
||||
*/
|
||||
private List<Integer> monitorResults;
|
||||
|
||||
private Boolean hasImage;
|
||||
|
||||
private String imageBase64;
|
||||
|
||||
private String imageContentType;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,14 @@ public interface IPqDevService extends IService<PqDev> {
|
||||
*/
|
||||
PqDevVO getPqDevById(String id);
|
||||
|
||||
/**
|
||||
* 下载设备图片
|
||||
*
|
||||
* @param id 设备id
|
||||
* @param response 响应
|
||||
*/
|
||||
void downloadImage(String id, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 获取装置信息和装置下监测点信息
|
||||
*
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@@ -37,6 +38,7 @@ import com.njcn.gather.device.pojo.po.PqDevSub;
|
||||
import com.njcn.gather.device.pojo.vo.*;
|
||||
import com.njcn.gather.device.service.IPqDevService;
|
||||
import com.njcn.gather.device.service.IPqDevSubService;
|
||||
import com.njcn.gather.device.util.PqDevImageSupport;
|
||||
import com.njcn.gather.monitor.pojo.po.PqMonitor;
|
||||
import com.njcn.gather.monitor.pojo.vo.PqMonitorExcel;
|
||||
import com.njcn.gather.monitor.service.IPqMonitorService;
|
||||
@@ -71,6 +73,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -138,7 +141,8 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
this.checkRepeat(pqDevParam, false);
|
||||
|
||||
PqDev pqDev = new PqDev();
|
||||
BeanUtil.copyProperties(pqDevParam, pqDev);
|
||||
BeanUtil.copyProperties(pqDevParam, pqDev, CopyOptions.create().setIgnoreProperties("image"));
|
||||
fillImage(pqDev, pqDevParam);
|
||||
String currrentScene = sysTestConfigService.getCurrrentScene();
|
||||
this.checkParams(pqDev, currrentScene);
|
||||
|
||||
@@ -169,6 +173,19 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
return this.save(pqDev);
|
||||
}
|
||||
|
||||
private void fillImage(PqDev pqDev, PqDevParam pqDevParam) {
|
||||
try {
|
||||
byte[] image = PqDevImageSupport.processUpload(pqDevParam.getImage());
|
||||
if (image != null) {
|
||||
pqDev.setImage(image);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, e.getMessage());
|
||||
} catch (IOException e) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, "图片处理失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验参数
|
||||
*
|
||||
@@ -211,7 +228,8 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
this.checkRepeat(updateParam, true);
|
||||
|
||||
PqDev pqDev = new PqDev();
|
||||
BeanUtil.copyProperties(updateParam, pqDev);
|
||||
BeanUtil.copyProperties(updateParam, pqDev, CopyOptions.create().setIgnoreProperties("image"));
|
||||
fillImage(pqDev, updateParam);
|
||||
String currrentScene = sysTestConfigService.getCurrrentScene();
|
||||
this.checkParams(pqDev, currrentScene);
|
||||
|
||||
@@ -278,6 +296,8 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
@Override
|
||||
public List<Map<String, Object>> listUnbound(String pattern) {
|
||||
List<PqDev> pqDevList = this.lambdaQuery()
|
||||
.select(PqDev::getId, PqDev::getName, PqDev::getDevType, PqDev::getManufacturer,
|
||||
PqDev::getCityName, PqDev::getGdName, PqDev::getSubName)
|
||||
.eq(PqDev::getPattern, pattern)
|
||||
.eq(PqDev::getState, DataStateEnum.ENABLE.getCode())
|
||||
.isNull(PqDev::getPlanId)
|
||||
@@ -392,6 +412,10 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
@Override
|
||||
public PqDevVO getPqDevById(String id) {
|
||||
PqDevVO pqDevVO = this.baseMapper.selectByDevId(id);
|
||||
if (ObjectUtil.isNull(pqDevVO)) {
|
||||
return null;
|
||||
}
|
||||
setImageEchoFields(pqDevVO);
|
||||
if (StrUtil.isNotBlank(pqDevVO.getSeries())) {
|
||||
pqDevVO.setSeries(EncryptionUtil.decoderString(1, pqDevVO.getSeries()));
|
||||
}
|
||||
@@ -420,6 +444,37 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
return pqDevVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadImage(String id, HttpServletResponse response) {
|
||||
PqDev pqDev = this.getById(id);
|
||||
if (ObjectUtil.isNull(pqDev) || pqDev.getImage() == null || pqDev.getImage().length == 0) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, "设备图片不存在");
|
||||
}
|
||||
String contentType = PqDevImageSupport.detectContentType(pqDev.getImage());
|
||||
String filename = "device-image-" + id + "." + PqDevImageSupport.getExtension(contentType);
|
||||
response.setContentType(contentType);
|
||||
response.setContentLength(pqDev.getImage().length);
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
|
||||
try {
|
||||
response.getOutputStream().write(pqDev.getImage());
|
||||
response.flushBuffer();
|
||||
} catch (IOException e) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, "设备图片下载失败");
|
||||
}
|
||||
}
|
||||
|
||||
private void setImageEchoFields(PqDevVO pqDevVO) {
|
||||
try {
|
||||
PqDevImageSupport.ImageEchoPayload payload = PqDevImageSupport.buildEchoPayload(pqDevVO.getImage());
|
||||
pqDevVO.setHasImage(payload.isHasImage());
|
||||
pqDevVO.setImageBase64(payload.getImageBase64());
|
||||
pqDevVO.setImageContentType(payload.getImageContentType());
|
||||
pqDevVO.setImage(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取查询条件wrapper
|
||||
@@ -429,6 +484,7 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
*/
|
||||
private Wrapper getQueryWrapper(PqDevParam.QueryParam queryParam) {
|
||||
QueryWrapper<PqDev> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.select("pq_dev.Id");
|
||||
if (ObjectUtil.isNotNull(queryParam)) {
|
||||
queryWrapper
|
||||
.like(StrUtil.isNotBlank(queryParam.getName()), "pq_dev.name", queryParam.getName())
|
||||
@@ -1659,7 +1715,10 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> listSelectOptions(String pattern) {
|
||||
List<PqDev> pqDevList = this.lambdaQuery().eq(PqDev::getPattern, pattern)
|
||||
List<PqDev> pqDevList = this.lambdaQuery()
|
||||
.select(PqDev::getCityName, PqDev::getGdName, PqDev::getSubName,
|
||||
PqDev::getHardwareVersion, PqDev::getSoftwareVersion)
|
||||
.eq(PqDev::getPattern, pattern)
|
||||
.eq(PqDev::getState, DataStateEnum.ENABLE.getCode())
|
||||
.list();
|
||||
String[] devKeyArray = new String[]{"cityName", "gdName", "subName", "hardwareVersion", "softwareVersion"};
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.njcn.gather.device.util;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Base64;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class PqDevImageSupport {
|
||||
|
||||
private static final long MAX_FILE_SIZE = 10L * 1024L * 1024L;
|
||||
private static final int MAX_EDGE = 1600;
|
||||
private static final float JPEG_QUALITY = 0.82f;
|
||||
|
||||
private PqDevImageSupport() {
|
||||
}
|
||||
|
||||
public static ImageEchoPayload buildEchoPayload(byte[] imageBytes) {
|
||||
if (imageBytes == null || imageBytes.length == 0) {
|
||||
return new ImageEchoPayload(false, null, null);
|
||||
}
|
||||
return new ImageEchoPayload(true, Base64.getEncoder().encodeToString(imageBytes), detectContentType(imageBytes));
|
||||
}
|
||||
|
||||
public static String detectContentType(byte[] imageBytes) {
|
||||
if (imageBytes == null || imageBytes.length < 4) {
|
||||
throw new IllegalArgumentException("图片内容无效");
|
||||
}
|
||||
if (isPng(imageBytes)) {
|
||||
return "image/png";
|
||||
}
|
||||
if (isJpeg(imageBytes)) {
|
||||
return "image/jpeg";
|
||||
}
|
||||
throw new IllegalArgumentException("仅支持 JPG、PNG 图片");
|
||||
}
|
||||
|
||||
public static byte[] processUpload(MultipartFile image) throws IOException {
|
||||
if (image == null || image.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (image.getSize() > MAX_FILE_SIZE) {
|
||||
throw new IllegalArgumentException("图片大小不能超过 10MB");
|
||||
}
|
||||
|
||||
String normalizedName = normalize(image.getOriginalFilename());
|
||||
String normalizedContentType = normalize(image.getContentType());
|
||||
boolean allowedType = normalizedContentType.equals("image/jpeg")
|
||||
|| normalizedContentType.equals("image/png")
|
||||
|| normalizedName.endsWith(".jpg")
|
||||
|| normalizedName.endsWith(".jpeg")
|
||||
|| normalizedName.endsWith(".png");
|
||||
if (!allowedType) {
|
||||
throw new IllegalArgumentException("仅支持 JPG、PNG 图片");
|
||||
}
|
||||
|
||||
byte[] originalBytes = image.getBytes();
|
||||
String contentType = detectContentType(originalBytes);
|
||||
BufferedImage source;
|
||||
try (InputStream inputStream = image.getInputStream()) {
|
||||
source = ImageIO.read(inputStream);
|
||||
}
|
||||
if (source == null) {
|
||||
throw new IllegalArgumentException("图片内容无效");
|
||||
}
|
||||
|
||||
BufferedImage target = scaleIfNeeded(source);
|
||||
if ("image/png".equals(contentType)) {
|
||||
return writePng(target);
|
||||
}
|
||||
return writeJpeg(target);
|
||||
}
|
||||
|
||||
public static String getExtension(String contentType) {
|
||||
return "image/png".equals(contentType) ? "png" : "jpg";
|
||||
}
|
||||
|
||||
private static BufferedImage scaleIfNeeded(BufferedImage source) {
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
int max = Math.max(width, height);
|
||||
if (max <= MAX_EDGE) {
|
||||
return source;
|
||||
}
|
||||
|
||||
double scale = (double) MAX_EDGE / max;
|
||||
int targetWidth = Math.max(1, (int) Math.round(width * scale));
|
||||
int targetHeight = Math.max(1, (int) Math.round(height * scale));
|
||||
int type = source.getType() == BufferedImage.TYPE_CUSTOM ? BufferedImage.TYPE_INT_ARGB : source.getType();
|
||||
BufferedImage target = new BufferedImage(targetWidth, targetHeight, type);
|
||||
Graphics2D graphics = target.createGraphics();
|
||||
try {
|
||||
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.drawImage(source, 0, 0, targetWidth, targetHeight, null);
|
||||
} finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private static byte[] writePng(BufferedImage image) throws IOException {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", outputStream);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] writeJpeg(BufferedImage image) throws IOException {
|
||||
BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = rgbImage.createGraphics();
|
||||
try {
|
||||
graphics.drawImage(image, 0, 0, null);
|
||||
} finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
|
||||
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
|
||||
if (!writers.hasNext()) {
|
||||
throw new IOException("未找到 JPG 图片编码器");
|
||||
}
|
||||
ImageWriter writer = writers.next();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream)) {
|
||||
writer.setOutput(imageOutputStream);
|
||||
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||
if (writeParam.canWriteCompressed()) {
|
||||
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
writeParam.setCompressionQuality(JPEG_QUALITY);
|
||||
}
|
||||
writer.write(null, new IIOImage(rgbImage, null, null), writeParam);
|
||||
} finally {
|
||||
writer.dispose();
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
private static boolean isPng(byte[] imageBytes) {
|
||||
return imageBytes.length >= 8
|
||||
&& (imageBytes[0] & 0xFF) == 0x89
|
||||
&& imageBytes[1] == 0x50
|
||||
&& imageBytes[2] == 0x4E
|
||||
&& imageBytes[3] == 0x47
|
||||
&& imageBytes[4] == 0x0D
|
||||
&& imageBytes[5] == 0x0A
|
||||
&& imageBytes[6] == 0x1A
|
||||
&& imageBytes[7] == 0x0A;
|
||||
}
|
||||
|
||||
private static boolean isJpeg(byte[] imageBytes) {
|
||||
return imageBytes.length >= 3
|
||||
&& (imageBytes[0] & 0xFF) == 0xFF
|
||||
&& (imageBytes[1] & 0xFF) == 0xD8
|
||||
&& (imageBytes[2] & 0xFF) == 0xFF;
|
||||
}
|
||||
|
||||
private static String normalize(String value) {
|
||||
return value == null ? "" : value.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class ImageEchoPayload {
|
||||
private boolean hasImage;
|
||||
private String imageBase64;
|
||||
private String imageContentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.njcn.gather.device.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PqDevImageSupportTest {
|
||||
|
||||
@Test
|
||||
public void buildEchoPayloadReturnsEmptyFieldsWhenImageMissing() {
|
||||
PqDevImageSupport.ImageEchoPayload payload = PqDevImageSupport.buildEchoPayload(null);
|
||||
|
||||
assertFalse(payload.isHasImage());
|
||||
assertNull(payload.getImageBase64());
|
||||
assertNull(payload.getImageContentType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildEchoPayloadDetectsPngAndCreatesBase64() throws Exception {
|
||||
byte[] imageBytes = createImageBytes("png");
|
||||
|
||||
PqDevImageSupport.ImageEchoPayload payload = PqDevImageSupport.buildEchoPayload(imageBytes);
|
||||
|
||||
assertTrue(payload.isHasImage());
|
||||
assertEquals("image/png", payload.getImageContentType());
|
||||
assertNotNull(payload.getImageBase64());
|
||||
assertFalse(payload.getImageBase64().isEmpty());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void detectContentTypeRejectsInvalidImageBytes() {
|
||||
PqDevImageSupport.detectContentType(new byte[]{1, 2, 3, 4});
|
||||
}
|
||||
|
||||
private byte[] createImageBytes(String format) throws Exception {
|
||||
BufferedImage image = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);
|
||||
image.setRGB(0, 0, Color.RED.getRGB());
|
||||
image.setRGB(1, 0, Color.GREEN.getRGB());
|
||||
image.setRGB(0, 1, Color.BLUE.getRGB());
|
||||
image.setRGB(1, 1, Color.WHITE.getRGB());
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, format, outputStream);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user