From 6546fc05f534fc9dea10781371fb6113b518bf28 Mon Sep 17 00:00:00 2001 From: "youhong.ai" Date: Mon, 3 Jul 2023 12:51:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/aiyh/utils/Util.java | 90 ++++++++ .../java/aiyh/utils/entity/DocImageInfo.java | 14 ++ .../java/aiyh/utils/entity/FieldViewInfo.java | 3 + .../java/aiyh/utils/mapper/UtilMapper.java | 28 ++- .../impl/CompressDocPictureImpl.java | 85 +++++++ .../mapper/CompressDocPictureMapper.java | 30 +++ .../util/CompressPictureUtil.java | 214 ++++++++++++++++++ .../java/youhong/ai/taibao/TestTaiBao.java | 2 +- .../youhong/ai/utiltest/ImageCompressor.java | 178 +++++++++++++++ .../ai/utiltest/UtilAPiResultTest.java | 202 +++++++++++++++++ .../utiltest/resultjsonparase/ParseTest.java | 170 ++++++++++++++ .../config/DetailTableAlias.java | 26 +++ .../config/DetailTableConfig.java | 31 +++ .../resultjsonparase/config/MainTable.java | 29 +++ 14 files changed, 1098 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java create mode 100644 src/main/java/com/customization/youhong/taibao/compresspicture/mapper/CompressDocPictureMapper.java create mode 100644 src/main/java/com/customization/youhong/taibao/compresspicture/util/CompressPictureUtil.java create mode 100644 src/test/java/youhong/ai/utiltest/ImageCompressor.java create mode 100644 src/test/java/youhong/ai/utiltest/UtilAPiResultTest.java create mode 100644 src/test/java/youhong/ai/utiltest/resultjsonparase/ParseTest.java create mode 100644 src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableAlias.java create mode 100644 src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableConfig.java create mode 100644 src/test/java/youhong/ai/utiltest/resultjsonparase/config/MainTable.java diff --git a/src/main/java/aiyh/utils/Util.java b/src/main/java/aiyh/utils/Util.java index 357e947..b1ff738 100644 --- a/src/main/java/aiyh/utils/Util.java +++ b/src/main/java/aiyh/utils/Util.java @@ -3034,6 +3034,10 @@ public class Util extends weaver.general.Util { return mapper.selectDocImageInfo(docId); } + public static DocImageInfo selectImageInfoByImageId(String imageFileId) { + return mapper.selectImageInfoByImageId(imageFileId); + } + /** * 查询文档信息 * @@ -3587,15 +3591,99 @@ public class Util extends weaver.general.Util { String field = matcher.group("field"); String otherKeyStr = matcher.group("other"); Object o = valueHandler(arg, field); + if (null == o) { throw new CustomerException(Util.logStr("can not get value of [{}] from [{}], this keyStr is [{}]", field, JSON.toJSONString(arg), keyStr)); } + if (o instanceof Collection) { + return new CustomerException("can not supper array value!"); + } return getValueByKeyStr(otherKeyStr, o); } throw new CustomerException("Unable to find value of key [" + keyStr + "]"); } + /** + *

通过keyStr获取value

+ * + * @param keyStr keyString + * @param arg map对象 + * @return value + */ + public static ValueOrList getValueOrListByKeyStr(String keyStr, Object arg) { + if (arg == null) { + return null; + } + if (!keyStr.contains(".")) { + Object o = valueHandler(arg, keyStr); + ValueOrList valueOrList = new ValueOrList(); + valueOrList.setValue(o); + valueOrList.setKey(keyStr); + return valueOrList; + } + String pattern = "(?^[\\w]+[\\w$]*)\\.*(?(\\S+)*)"; + Pattern compile = Pattern.compile(pattern); + Matcher matcher = compile.matcher(keyStr); + if (matcher.find()) { + String field = matcher.group("field"); + String otherKeyStr = matcher.group("other"); + Object o = valueHandler(arg, field); + if (null == o) { + throw new CustomerException(Util.logStr("can not get value of [{}] from [{}], this keyStr is [{}]", + field, JSON.toJSONString(arg), keyStr)); + } + if (o instanceof Collection) { + ValueOrList valueOrList = new ValueOrList(); + valueOrList.setValue(o); + valueOrList.setArray(true); + valueOrList.setKey(field); + return valueOrList; + } + return getValueOrListByKeyStr(otherKeyStr, o); + } + throw new CustomerException("Unable to find value of key [" + keyStr + "]"); + } + + public static class ValueOrList { + private String key; + private boolean isArray; + private Object value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public boolean isArray() { + return isArray; + } + + public void setArray(boolean array) { + isArray = array; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + @Override + public String toString() { + return "ValueOrList{" + + "key='" + key + '\'' + + ", isArray=" + isArray + + ", value=" + value + + '}'; + } + } + /** *

获取value

* @@ -3979,4 +4067,6 @@ public class Util extends weaver.general.Util { } } } + + } diff --git a/src/main/java/aiyh/utils/entity/DocImageInfo.java b/src/main/java/aiyh/utils/entity/DocImageInfo.java index f224ac6..f3b3136 100644 --- a/src/main/java/aiyh/utils/entity/DocImageInfo.java +++ b/src/main/java/aiyh/utils/entity/DocImageInfo.java @@ -41,4 +41,18 @@ public class DocImageInfo { /** 文件类型 */ @SqlOracleDbFieldAnn("DOC_FILE_TYPE") private Integer docFileType; + /** 文件路径 */ + @SqlOracleDbFieldAnn("PATH") + private String path; + + /** 加密code */ + @SqlOracleDbFieldAnn("AES_CODE") + private String aesCode; + + /** 文件token */ + @SqlOracleDbFieldAnn("TOKEN_KEY") + private String tokenKey; + /** 缩略图 */ + @SqlOracleDbFieldAnn("MINI_IMG_PATH") + private String miniImgPath; } diff --git a/src/main/java/aiyh/utils/entity/FieldViewInfo.java b/src/main/java/aiyh/utils/entity/FieldViewInfo.java index 0240c5f..d1a5c74 100644 --- a/src/main/java/aiyh/utils/entity/FieldViewInfo.java +++ b/src/main/java/aiyh/utils/entity/FieldViewInfo.java @@ -46,4 +46,7 @@ public class FieldViewInfo { @SqlOracleDbFieldAnn("FIELD_HTML_TYPE") private String fieldHtmlType; + + + private Object value; } diff --git a/src/main/java/aiyh/utils/mapper/UtilMapper.java b/src/main/java/aiyh/utils/mapper/UtilMapper.java index 7382768..9cb8bd6 100644 --- a/src/main/java/aiyh/utils/mapper/UtilMapper.java +++ b/src/main/java/aiyh/utils/mapper/UtilMapper.java @@ -56,28 +56,34 @@ public interface UtilMapper { @Select("select di.id id,dc.id doc_id," + + "img.FILEREALPATH path,img.AESCODE aes_code,img.TOKENKEY token_key,MINIIMGPATH mini_img_path," + "di.imagefileid image_file_id," + "dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," + - "(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " + + "(case when di.imagefilename = '' or di.imagefilename is null then dc.DOCSUBJECT else di.imagefilename end) image_file_name " + "from DocDetail dc " + + "left join imagefile img on img.IMAGEFILEID = di.IMAGEFILEID " + "left join docimagefile di on (dc.id = #{docId} and dc.id = di.docid) " + "where dc.id = #{docId} ") DocImageInfo selectDocImageInfo(@ParamMapper("docId") String docId); @Select("select di.id id,dc.id doc_id," + + "img.FILEREALPATH path,img.AESCODE aes_code,img.TOKENKEY token_key,MINIIMGPATH mini_img_path," + "di.imagefileid image_file_id, di.docfiletype doc_file_type," + "dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," + - "(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " + + "(case when di.imagefilename = '' or di.imagefilename is null then dc.DOCSUBJECT else di.imagefilename end) image_file_name " + "from DocDetail dc " + + "left join imagefile img on img.IMAGEFILEID = di.IMAGEFILEID " + "left join docimagefile di on (dc.id in ($t{docIds}) and dc.id = di.docid )" + "where dc.id in ($t{docIds})") List selectDocImageInfos(@ParamMapper("docIds") String docIds); @Select("select di.id id,dc.id doc_id," + + "img.FILEREALPATH path,img.AESCODE aes_code,img.TOKENKEY token_key,MINIIMGPATH mini_img_path," + "di.imagefileid image_file_id, di.docfiletype doc_file_type," + "dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," + - "(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " + + "(case when di.imagefilename = '' or di.imagefilename is null then dc.DOCSUBJECT else di.imagefilename end) image_file_name " + "from DocDetail dc " + + "left join imagefile img on img.IMAGEFILEID = di.IMAGEFILEID " + "left join docimagefile di on (dc.id in ($t{docIds}) and dc.id = di.docid )" + "where dc.id in ($t{docIds})") List selectDocImageInfos(@ParamMapper("docIds") String[] docIds); @@ -197,4 +203,20 @@ public interface UtilMapper { @Select("select id, tablename table_name, indexdesc index_desc from mode_bill_info_view where id = #{id}") ModelTableInfo selectModelTableInfo(Integer id); + + @Select("select di.id id,dc.id doc_id, " + + "img.FILEREALPATH path,img.AESCODE aes_code,img.TOKENKEY token_key,img.MINIIMGPATH mini_img_path," + + " di.imagefileid image_file_id, " + + " dc.DOCCREATEDATE doc_create_date, " + + " dc.DOCCREATETIME doc_create_time, " + + " (case when " + + " di.imagefilename = '' or di.imagefilename is null " + + " then dc.DOCSUBJECT " + + " else di.imagefilename end " + + " ) image_file_name " + + "from imagefile img " + + "left join docimagefile di on img.IMAGEFILEID = di.IMAGEFILEID " + + "left join docdetail dc on di.DOCID = dc.ID " + + " where img.IMAGEFILEID = #{imageId}") + DocImageInfo selectImageInfoByImageId(String imageFileId); } diff --git a/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java b/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java new file mode 100644 index 0000000..99a4f40 --- /dev/null +++ b/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java @@ -0,0 +1,85 @@ +package com.customization.youhong.taibao.compresspicture.impl; + +import aiyh.utils.Util; +import aiyh.utils.entity.DocImageInfo; +import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil; +import aiyh.utils.tool.cn.hutool.core.util.StrUtil; +import com.api.doc.detail.util.DocDownloadCheckUtil; +import com.customization.youhong.taibao.compresspicture.mapper.CompressDocPictureMapper; +import com.customization.youhong.taibao.compresspicture.util.CompressPictureUtil; +import com.weaverboot.frame.ioc.anno.classAnno.WeaIocReplaceComponent; +import com.weaverboot.frame.ioc.anno.methodAnno.WeaReplaceAfter; +import com.weaverboot.frame.ioc.handler.replace.weaReplaceParam.impl.WeaAfterReplaceParam; +import org.apache.log4j.Logger; +import weaver.file.ImageFileManager; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + *

压缩图片

+ * + *

create: 2023/7/1 16:17

+ * + * @author youHong.ai + */ + +@WeaIocReplaceComponent("CompressDocPictureService") +public class CompressDocPictureImpl { + + private final CompressDocPictureMapper mapper = Util.getMapper(CompressDocPictureMapper.class); + + private final Logger log = Util.getLogger(); + + /** + * 这个是接口后置方法,大概的用法跟前置方法差不多,稍有差别 + * 注解名称为WeaReplaceAfter + * 返回类型必须为String + * 参数叫WeaAfterReplaceParam,这个类前四个参数跟前置方法的那个相同,不同的是多了一个叫data的String,这个是那个接口执行完返回的报文 + * 你可以对那个报文进行操作,然后在这个方法里return回去 + */ + @WeaReplaceAfter(value = "/api/doc/save/save", order = 1) + public String after(WeaAfterReplaceParam weaAfterReplaceParam) { + String data = weaAfterReplaceParam.getData(); + try { + Map paramMap = weaAfterReplaceParam.getParamMap(); + String doccontent = Util.null2String(paramMap.get("doccontent")); + if (StrUtil.isBlank(doccontent)) { + return data; + } + List imgSrcList = CompressPictureUtil.parseImageSrc(doccontent); + if (CollectionUtil.isEmpty(imgSrcList)) { + return data; + } + for (String imgSrc : imgSrcList) { + String imageFileIdEncrypt = CompressPictureUtil.extractFileId(imgSrc); + String imageFileId = DocDownloadCheckUtil.DncodeFileid(imageFileIdEncrypt); + DocImageInfo docImageInfo = Util.selectImageInfoByImageId(imageFileId); + if (StrUtil.isNotBlank(docImageInfo.getMiniImgPath())) { + continue; + } + InputStream inputStreamById = ImageFileManager.getInputStreamById(Integer.parseInt(imageFileId)); + InputStream quality = CompressPictureUtil.compressImage(inputStreamById, docImageInfo.getImageFileName(), + Float.parseFloat(Util.getCusConfigValueNullOrEmpty("quality", "0.5"))); + if (Objects.isNull(quality)) { + continue; + } + int newImageFileId = Util.createFileByInputSteam(quality, docImageInfo.getImageFileName()); + if (newImageFileId <= 0) { + continue; + } + DocImageInfo newDocImageInfo = Util.selectImageInfoByImageId(Util.null2String(newImageFileId)); + boolean flag = mapper.updateImageInfo(docImageInfo, newDocImageInfo); + if (flag) { + mapper.updateImageInfo(docImageInfo, newDocImageInfo); + } + } + } catch (Exception e) { + log.error("压缩文件出现异常:" + Util.getErrString(e)); + } + // 这个就是接口执行完的报文 + return data; + } +} diff --git a/src/main/java/com/customization/youhong/taibao/compresspicture/mapper/CompressDocPictureMapper.java b/src/main/java/com/customization/youhong/taibao/compresspicture/mapper/CompressDocPictureMapper.java new file mode 100644 index 0000000..37718b6 --- /dev/null +++ b/src/main/java/com/customization/youhong/taibao/compresspicture/mapper/CompressDocPictureMapper.java @@ -0,0 +1,30 @@ +package com.customization.youhong.taibao.compresspicture.mapper; + +import aiyh.utils.annotation.recordset.ParamMapper; +import aiyh.utils.annotation.recordset.SqlMapper; +import aiyh.utils.annotation.recordset.Update; +import aiyh.utils.entity.DocImageInfo; + +/** + *

+ * + *

create: 2023/7/1 16:41

+ * + * @author youHong.ai + */ +@SqlMapper +public interface CompressDocPictureMapper { + + /** + *

更新文件信息

+ * @param docImageInfo 老文件信息 + * @param newDocImageInfo 新文件信息 + * @return 是否更新成功 + */ + + @Update("update imagefile set FILEREALPATH = #{new.path},AESCODE = #{new.aesCode}," + + "TOKENKEY = #{new.tokenKey},FILESIZE = #{new.fileSize}," + + "MINIIMGPATH= #{old.imageFileId} where IMAGEFILEID = #{old.imageFileId}") + boolean updateImageInfo(@ParamMapper("old") DocImageInfo docImageInfo, + @ParamMapper("new") DocImageInfo newDocImageInfo); +} diff --git a/src/main/java/com/customization/youhong/taibao/compresspicture/util/CompressPictureUtil.java b/src/main/java/com/customization/youhong/taibao/compresspicture/util/CompressPictureUtil.java new file mode 100644 index 0000000..07ab5d9 --- /dev/null +++ b/src/main/java/com/customization/youhong/taibao/compresspicture/util/CompressPictureUtil.java @@ -0,0 +1,214 @@ +package com.customization.youhong.taibao.compresspicture.util; + +import aiyh.utils.excention.CustomerException; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + *

压缩工具类

+ * + *

create: 2023/7/1 16:20

+ * + * @author youHong.ai + */ +public class CompressPictureUtil { + + /** + *

压缩图片

+ * + * @param inputStream 图片文件流 + * @param fileName 文件名称 + * @param quality 图片质量 + * @return 压缩后的文件 + */ + public static InputStream compressImage(InputStream inputStream, String fileName, float quality) { + try { + // 读取输入图像流 + BufferedImage image = ImageIO.read(inputStream); + + // 获取图像格式 + String formatName = getFormatName(fileName); + + // 根据图像格式进行不同的压缩处理 + if (formatName.equalsIgnoreCase("png")) { + return compressPNG(image, quality); + } else if (formatName.equalsIgnoreCase("jepg")) { + return compressJPEG(image, quality); + } else { + return null; + } + } catch (IOException e) { + throw new CustomerException(e); + } + } + + /** + *

压缩png文件

+ * + * @param image 图片 + * @param quality 图片质量 + * @return 压缩后文件 + * @throws IOException io异常 + */ + private static InputStream compressPNG(BufferedImage image, float quality) throws IOException { + int originalWidth = image.getWidth(); + int originalHeight = image.getHeight(); + + // 计算压缩后的宽度和高度 + int compressedWidth = (int) (originalWidth * quality); + int compressedHeight = (int) (originalHeight * quality); + + // 创建压缩后的图像 + BufferedImage compressedImage = new BufferedImage(compressedWidth, compressedHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = compressedImage.createGraphics(); + g2d.drawImage(image, 0, 0, compressedWidth, compressedHeight, null); + g2d.dispose(); + + // 将压缩后的图像保存到字节数组输出流 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageIO.write(compressedImage, "png", outputStream); + + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + /** + *

压缩jpeg图片

+ * + * @param image 图片 + * @param quality 图片质量 + * @return 压缩后图片 + * @throws IOException io异常 + */ + + private static InputStream compressJPEG(BufferedImage image, float quality) throws IOException { + // 创建压缩参数 + ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writeParam.setCompressionQuality(quality); + + // 将压缩后的图像保存到字节数组输出流 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream); + writer.setOutput(imageOutputStream); + writer.write(null, new IIOImage(image, null, null), writeParam); + + // 关闭资源 + writer.dispose(); + imageOutputStream.close(); + outputStream.close(); + + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + /** + *

格式化图片后缀

+ * + * @param fileName 文件名称 + * @return 文件后缀 + */ + private static String getFormatName(String fileName) { + String formatName = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); + if (formatName.equals("jpg") || formatName.equals("jpeg")) { + return "jpeg"; + } + return formatName; + } + + /** + *

解析html中的img的src

+ * + * @param html html字符串 + * @return 所有的src + */ + public static List parseImageSrc(String html) { + List srcList = new ArrayList<>(); + + // 使用 Jsoup 解析 HTML 字符串 + Document document = Jsoup.parse(html); + + // 获取所有的 img 标签 + Elements imgElements = document.select("img"); + + // 使用迭代器遍历 img 标签,并获取其 src 属性值 + Iterator iterator = imgElements.iterator(); + while (iterator.hasNext()) { + Element imgElement = iterator.next(); + String src = imgElement.attr("src"); + srcList.add(src); + } + + return srcList; + } + + /** + *

获取文件id

+ * + * @param input 输入字符串 + * @return 文件id + */ + public static String extractFileId(String input) { + String fileId = null; + + // 寻找 "fileid=" 的索引位置 + int index = input.indexOf("fileid="); + if (index != -1) { + // 截取 "fileid=" 后面的部分 + String substring = input.substring(index + 7); + + // 查找第一个 "&" 符号的索引位置 + int endIndex = substring.indexOf("&"); + if (endIndex != -1) { + // 截取从 "fileid=" 后面到第一个 "&" 符号之前的部分 + fileId = substring.substring(0, endIndex); + } else { + // 如果没有 "&" 符号,截取从 "fileid=" 后面到字符串末尾的部分 + fileId = substring; + } + } + + return fileId; + } + + /** + *

替换fieldId

+ * + * @param input 带替换的字符串 + * @param newFileId 新文件id + * @return 完整字符串 + */ + public static String replaceFileId(String input, String newFileId) { + // 寻找 "fileid=" 的索引位置 + int index = input.indexOf("fileid="); + if (index != -1) { + // 查找第一个 "&" 符号的索引位置 + int endIndex = input.indexOf("&", index); + if (endIndex != -1) { + // 替换 "fileid=" 后面到第一个 "&" 符号之前的部分 + return input.substring(0, index + 7) + newFileId + input.substring(endIndex); + } else { + // 替换 "fileid=" 后面到字符串末尾的部分 + return input.substring(0, index + 7) + newFileId; + } + } + + return input; + } +} diff --git a/src/test/java/youhong/ai/taibao/TestTaiBao.java b/src/test/java/youhong/ai/taibao/TestTaiBao.java index 5982a67..77ee856 100644 --- a/src/test/java/youhong/ai/taibao/TestTaiBao.java +++ b/src/test/java/youhong/ai/taibao/TestTaiBao.java @@ -198,6 +198,6 @@ public class TestTaiBao extends BaseTest { @Test public void testjlsdfj() { - System.out.println(DocDownloadCheckUtil.DncodeFileid("a1c0c56773deeff8d8f7f235f3eb3db0d2b34cbedb9ff32262414a3c6c4b9a393fc01656cc42ddaf07cd9319d68901a734f710fbddd167603")); + System.out.println(DocDownloadCheckUtil.DncodeFileid("a5f32cb1a24896143ca3fd93e0a5c607025a5f365a565ba4f2b6c1953e67cd25f818d80a51ade71c550289e5065f9a2f22f2a2a27772bc6eb")); } } diff --git a/src/test/java/youhong/ai/utiltest/ImageCompressor.java b/src/test/java/youhong/ai/utiltest/ImageCompressor.java new file mode 100644 index 0000000..a3accb0 --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/ImageCompressor.java @@ -0,0 +1,178 @@ +package youhong.ai.utiltest; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ImageCompressor { + public static InputStream compressImage(InputStream inputStream, String fileName, float quality) { + try { + // 读取输入图像流 + BufferedImage image = ImageIO.read(inputStream); + + // 获取图像格式 + String formatName = getFormatName(fileName); + + // 根据图像格式进行不同的压缩处理 + if (formatName.equals("png")) { + return compressPNG(image, quality); + } else { + return compressJPEG(image, quality); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + private static InputStream compressPNG(BufferedImage image, float quality) throws IOException { + int originalWidth = image.getWidth(); + int originalHeight = image.getHeight(); + + // 计算压缩后的宽度和高度 + int compressedWidth = (int) (originalWidth * quality); + int compressedHeight = (int) (originalHeight * quality); + + // 创建压缩后的图像 + BufferedImage compressedImage = new BufferedImage(compressedWidth, compressedHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = compressedImage.createGraphics(); + g2d.drawImage(image, 0, 0, compressedWidth, compressedHeight, null); + g2d.dispose(); + + // 将压缩后的图像保存到字节数组输出流 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageIO.write(compressedImage, "png", outputStream); + + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + private static InputStream compressJPEG(BufferedImage image, float quality) throws IOException { + // 创建压缩参数 + ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writeParam.setCompressionQuality(quality); + + // 将压缩后的图像保存到字节数组输出流 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream); + writer.setOutput(imageOutputStream); + writer.write(null, new IIOImage(image, null, null), writeParam); + + // 关闭资源 + writer.dispose(); + imageOutputStream.close(); + outputStream.close(); + + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + private static String getFormatName(String fileName) { + String formatName = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); + if (formatName.equals("jpg") || formatName.equals("jpeg")) { + return "jpeg"; + } + return formatName; + } + + public static List parseImageSrc(String html) { + List srcList = new ArrayList<>(); + + // 使用 Jsoup 解析 HTML 字符串 + Document document = Jsoup.parse(html); + + // 获取所有的 img 标签 + Elements imgElements = document.select("img"); + + // 使用迭代器遍历 img 标签,并获取其 src 属性值 + Iterator iterator = imgElements.iterator(); + while (iterator.hasNext()) { + Element imgElement = iterator.next(); + String src = imgElement.attr("src"); + srcList.add(src); + } + + return srcList; + } + + public static String extractFileId(String input) { + String fileId = null; + + // 寻找 "fileid=" 的索引位置 + int index = input.indexOf("fileid="); + if (index != -1) { + // 截取 "fileid=" 后面的部分 + String substring = input.substring(index + 7); + + // 查找第一个 "&" 符号的索引位置 + int endIndex = substring.indexOf("&"); + if (endIndex != -1) { + // 截取从 "fileid=" 后面到第一个 "&" 符号之前的部分 + fileId = substring.substring(0, endIndex); + } else { + // 如果没有 "&" 符号,截取从 "fileid=" 后面到字符串末尾的部分 + fileId = substring; + } + } + + return fileId; + } + + public static void main(String[] args) throws FileNotFoundException { + List strings = parseImageSrc("\n" + + "\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\n" + + "\n" + + "

alkjasf

\n" + + "\n" + + "

\"\"

\n" + + "\n" + + "

\"\"

\n" + + "\n" + + "\n"); + System.out.println(strings); + for (String string : strings) { + String s = extractFileId(string); + System.out.println(s); + } + // // 示例用法 + // InputStream inputStream = new FileInputStream("/Users/aoey.oct.22/Pictures/PleaseLookForwardToIt.png"); + // InputStream compressedInputStream = compressImage(inputStream, "PleaseLookForwardToIt.png", 0.5f); + // if (compressedInputStream != null) { + // // 将压缩后的输入流写入到文件中 + // String outputFilePath = "/Users/aoey.oct.22/Pictures/PleaseLookForwardToIt_yasuo_1.png"; + // try (OutputStream outputStream = new FileOutputStream(outputFilePath)) { + // byte[] buffer = new byte[1024]; + // int bytesRead; + // while ((bytesRead = compressedInputStream.read(buffer)) != -1) { + // outputStream.write(buffer, 0, bytesRead); + // } + // System.out.println("压缩后的图像文件已保存:" + outputFilePath); + // } catch (IOException e) { + // e.printStackTrace(); + // } + // } + } +} + + + diff --git a/src/test/java/youhong/ai/utiltest/UtilAPiResultTest.java b/src/test/java/youhong/ai/utiltest/UtilAPiResultTest.java new file mode 100644 index 0000000..c69670f --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/UtilAPiResultTest.java @@ -0,0 +1,202 @@ +package youhong.ai.utiltest; + +import aiyh.utils.Util; +import aiyh.utils.entity.FieldViewInfo; +import aiyh.utils.excention.CustomerException; +import aiyh.utils.tool.cn.hutool.core.bean.BeanUtil; +import basetest.BaseTest; +import com.alibaba.fastjson.JSON; +import org.junit.Test; +import youhong.ai.mymapper.util.Builder; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

测试

+ * + *

create: 2023/7/1 18:33

+ * + * @author youHong.ai + */ +public class UtilAPiResultTest extends BaseTest { + + + @Test + public void test() { + List> dt1 = new ArrayList>() {{ + add(new HashMap() {{ + put("apiPath", "data.name"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "main") + .with(FieldViewInfo::setFieldName, "name") + .build()); + + }}); + add(new HashMap() {{ + put("apiPath", "data.age"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "main") + .with(FieldViewInfo::setFieldName, "age") + .build()); + }}); + add(new HashMap() {{ + put("apiPath", "workList.time"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "dt_1") + .with(FieldViewInfo::setFieldName, "time") + .build()); + }}); + add(new HashMap() {{ + put("apiPath", "workList.title"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "dt_1") + .with(FieldViewInfo::setFieldName, "title") + .build()); + }}); + add(new HashMap() {{ + put("apiPath", "friends.name"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "dt_2") + .with(FieldViewInfo::setFieldName, "name") + .build()); + }}); + add(new HashMap() {{ + put("apiPath", "friends.age"); + put("field", Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setTableName, "dt_2") + .with(FieldViewInfo::setFieldName, "age") + .build()); + }}); + }}; + List> dt2 = new ArrayList>() {{ + add(new HashMap() {{ + put("apiPath", "data.workList"); + put("alias", "workList"); + }}); + add(new HashMap() {{ + put("apiPath", "data.friends"); + put("alias", "friends"); + }}); + }}; + + Map result = new HashMap() {{ + put("code", 200); + put("data", new HashMap() {{ + put("name", "test"); + put("age", "18"); + put("workList", new ArrayList>() {{ + add(new HashMap() {{ + put("time", "2023-07-01"); + put("title", "吃饭"); + }}); + add(new HashMap() {{ + put("time", "2023-07-02"); + put("title", "写代码"); + }}); + add(new HashMap() {{ + put("time", "2023-07-03"); + put("title", "睡觉"); + }}); + }}); + put("friends", new ArrayList>() {{ + add(new HashMap() {{ + put("name", "xiao"); + put("age", 18); + }}); + add(new HashMap() {{ + put("name", "wang"); + put("age", 18); + }}); + add(new HashMap() {{ + put("name", "he"); + put("age", 18); + }}); + }}); + }}); + }}; + Map bigMap = new HashMap<>(); + Map tempResult = new HashMap<>(result); + for (Map map : dt2) { + tempResult.putAll(bigMap); + Object apiPathObj = parentIsArray(Util.null2String(map.get("apiPath")), tempResult); + bigMap.put(Util.null2String(map.get("alias")), apiPathObj); + } + bigMap.put("data", result.get("data")); + System.out.println(JSON.toJSONString(bigMap)); + List>> list = new ArrayList<>(); + for (Map map : dt1) { + String apiPath = Util.null2String(map.get("apiPath")); + Object o = parentIsArray(apiPath, bigMap); + if (o instanceof Collection) { + List> listMap = (List>) o; + List> tempList = new ArrayList<>(); + for (Map obj : listMap) { + Map tempMap = new HashMap<>(); + tempMap.put(apiPath.split("\\.")[0], obj); + Object value = Util.getValueByKeyStr(apiPath, tempMap); + Map mappingMap = new HashMap<>(); + mappingMap.put("config", map); + mappingMap.put("value", value); + tempList.add(mappingMap); + } + list.add(tempList); + + } else { + List> tempList = new ArrayList<>(); + Map mappingMap = new HashMap<>(); + mappingMap.put("config", map); + mappingMap.put("value", o); + tempList.add(mappingMap); + list.add(tempList); + } + } + Map> finalConfig = new HashMap<>(); + List fieldList = new ArrayList<>(); + + System.out.println(JSON.toJSONString(list)); + for (List> maps : list) { + System.out.println(JSON.toJSONString(maps)); + for (Map map : maps) { + Map config = (Map) map.get("config"); + FieldViewInfo field = (FieldViewInfo) config.get("field"); + FieldViewInfo target = new FieldViewInfo(); + BeanUtil.copyProperties(field, target); + target.setValue(map.get("value")); + fieldList.add(target); + } + } + System.out.println(JSON.toJSONString(fieldList)); + } + + public Object parentIsArray(String keyStr, Object arg) { + if (arg == null) { + return null; + } + if (!keyStr.contains(".")) { + return valueHandler(arg, keyStr); + } + String pattern = "(?^[\\w]+[\\w$]*)\\.*(?(\\S+)*)"; + Pattern compile = Pattern.compile(pattern); + Matcher matcher = compile.matcher(keyStr); + if (matcher.find()) { + String field = matcher.group("field"); + String otherKeyStr = matcher.group("other"); + Object o = valueHandler(arg, field); + if (null == o) { + throw new CustomerException(Util.logStr("can not get value of [{}] from [{}], this keyStr is [{}]", + field, JSON.toJSONString(arg), keyStr)); + } + if (o instanceof Collection) { + return o; + } + return parentIsArray(otherKeyStr, o); + } + throw new CustomerException("Unable to find value of key [" + keyStr + "]"); + } + + private Object valueHandler(Object obj, String key) { + return ((Map) obj).get(key); + } +} diff --git a/src/test/java/youhong/ai/utiltest/resultjsonparase/ParseTest.java b/src/test/java/youhong/ai/utiltest/resultjsonparase/ParseTest.java new file mode 100644 index 0000000..f227936 --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/resultjsonparase/ParseTest.java @@ -0,0 +1,170 @@ +package youhong.ai.utiltest.resultjsonparase; + +import aiyh.utils.Util; +import aiyh.utils.entity.FieldViewInfo; +import aiyh.utils.tool.cn.hutool.core.bean.BeanUtil; +import basetest.BaseTest; +import com.alibaba.fastjson.JSON; +import org.junit.Test; +import youhong.ai.mymapper.util.Builder; +import youhong.ai.utiltest.resultjsonparase.config.DetailTableAlias; +import youhong.ai.utiltest.resultjsonparase.config.DetailTableConfig; +import youhong.ai.utiltest.resultjsonparase.config.MainTable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

解析测试

+ * + *

create: 2023/7/3 11:22

+ * + * @author youHong.ai + */ + +public class ParseTest extends BaseTest { + + + @Test + public void test() { + MainTable baseData = getBaseData(); + Map resultData = getResultData(); + List aliasesList = baseData.getAliasesList(); + Map resultParas = new HashMap<>(); + Map dateMap = new HashMap<>(resultData); + for (DetailTableAlias detailTableAlia : aliasesList) { + String alias = detailTableAlia.getAlias(); + Object valueByKeyStr = Util.getValueByKeyStr(detailTableAlia.getApiPath(), dateMap); + resultParas.put(alias, valueByKeyStr); + dateMap.put(alias, valueByKeyStr); + } + resultParas.put("data", resultData); + List mappings = baseData.getMappings(); + Map> parseMap = new HashMap<>(); + for (DetailTableConfig mapping : mappings) { + String apiPath = mapping.getApiPath(); + String tableName = mapping.getFieldViewInfo().getTableName(); + Util.ValueOrList valueOrListByKeyStr = Util.getValueOrListByKeyStr(apiPath, resultParas); + List rowList = new ArrayList<>(); + Object value = valueOrListByKeyStr.getValue(); + if (valueOrListByKeyStr.isArray()) { + // 数组,需要循环 + List> list = (List>) value; + int n = 0; + for (Map map : list) { + Map tempMap = new HashMap<>(); + tempMap.put(valueOrListByKeyStr.getKey(), map); + Object valueByKeyStr = Util.getValueByKeyStr(mapping.getApiPath(), tempMap); + DetailTableConfig target = new DetailTableConfig(); + BeanUtil.copyProperties(mapping, target); + target.setValue(valueByKeyStr); + FieldViewInfo fieldTarget = new FieldViewInfo(); + BeanUtil.copyProperties(mapping.getFieldViewInfo(), fieldTarget); + target.setFieldViewInfo(fieldTarget); + target.setIndex(n++); + rowList.add(target); + } + } else { + mapping.setValue(value); + rowList.add(mapping); + } + if (parseMap.containsKey(tableName)) { + List detailTableConfigs = parseMap.get(tableName); + detailTableConfigs.addAll(rowList); + } else { + parseMap.put(tableName, rowList); + } + + } + Map>> finalMap = new HashMap<>(); + for (Map.Entry> entry : parseMap.entrySet()) { + List value = entry.getValue(); + Map> collect = value.stream().collect(Collectors.groupingBy(item -> Util.null2String(item.getIndex() + ""))); + List> collect1 = collect.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList()); + finalMap.put(entry.getKey(), collect1); + } + System.out.println(JSON.toJSONString(finalMap)); + } + + + public Map getResultData() { + Map result = new HashMap<>(); + Map data = new HashMap<>(); + data.put("name", "肖博亢"); + data.put("age", 18); + data.put("sex", "女"); + List> friends = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + Map friend = new HashMap<>(); + friend.put("name", "friend" + i); + friend.put("age", i); + friend.put("sex", "未知"); + friends.add(friend); + } + data.put("friends", friends); + result.put("data", data); + result.put("code", 200); + return result; + } + + + public MainTable getBaseData() { + MainTable mainTable = new MainTable(); + ArrayList mappings = new ArrayList<>(); + DetailTableConfig detailTableConfig = new DetailTableConfig(); + detailTableConfig.setApiPath("data.name"); + detailTableConfig.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "name") + .with(FieldViewInfo::setTableName, "main") + .build()); + mappings.add(detailTableConfig); + DetailTableConfig detailTableConfig1 = new DetailTableConfig(); + detailTableConfig1.setApiPath("data.age"); + detailTableConfig1.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "age") + .with(FieldViewInfo::setTableName, "main") + .build()); + mappings.add(detailTableConfig1); + DetailTableConfig detailTableConfig2 = new DetailTableConfig(); + detailTableConfig2.setApiPath("data.sex"); + detailTableConfig2.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "sex") + .with(FieldViewInfo::setTableName, "main") + .build()); + mappings.add(detailTableConfig2); + DetailTableConfig detailTableConfig3 = new DetailTableConfig(); + detailTableConfig3.setApiPath("friends.sex"); + detailTableConfig3.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "sex") + .with(FieldViewInfo::setTableName, "detail_1") + .build()); + mappings.add(detailTableConfig3); + DetailTableConfig detailTableConfig4 = new DetailTableConfig(); + detailTableConfig4.setApiPath("friends.name"); + detailTableConfig4.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "name") + .with(FieldViewInfo::setTableName, "detail_1") + .build()); + mappings.add(detailTableConfig4); + DetailTableConfig detailTableConfig5 = new DetailTableConfig(); + detailTableConfig5.setApiPath("friends.age"); + detailTableConfig5.setFieldViewInfo(Builder.builder(FieldViewInfo::new) + .with(FieldViewInfo::setFieldName, "age") + .with(FieldViewInfo::setTableName, "detail_1") + .build()); + mappings.add(detailTableConfig5); + mainTable.setMappings(mappings); + ArrayList aliasesList = new ArrayList<>(); + DetailTableAlias detailTableAlias = new DetailTableAlias(); + detailTableAlias.setAlias("friends"); + detailTableAlias.setApiPath("data.friends"); + aliasesList.add(detailTableAlias); + mainTable.setAliasesList(aliasesList); + return mainTable; + } + + +} diff --git a/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableAlias.java b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableAlias.java new file mode 100644 index 0000000..b4b9c5b --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableAlias.java @@ -0,0 +1,26 @@ +package youhong.ai.utiltest.resultjsonparase.config; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + *

+ * + *

create: 2023/7/3 11:23

+ * + * @author youHong.ai + */ +@Getter +@Setter +@ToString +public class DetailTableAlias { + + + private String apiPath; + + + // 别名 + private String alias; +} + diff --git a/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableConfig.java b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableConfig.java new file mode 100644 index 0000000..85d986e --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/DetailTableConfig.java @@ -0,0 +1,31 @@ +package youhong.ai.utiltest.resultjsonparase.config; + +import aiyh.utils.entity.FieldViewInfo; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + *

+ * + *

create: 2023/7/3 11:23

+ * + * @author youHong.ai + */ +@Getter +@Setter +@ToString +public class DetailTableConfig { + + private String apiPath; + + + private FieldViewInfo fieldViewInfo; + + private Object value; + + + private Integer index; + +// 一些其他的配置字段信息 +} diff --git a/src/test/java/youhong/ai/utiltest/resultjsonparase/config/MainTable.java b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/MainTable.java new file mode 100644 index 0000000..0e3c358 --- /dev/null +++ b/src/test/java/youhong/ai/utiltest/resultjsonparase/config/MainTable.java @@ -0,0 +1,29 @@ +package youhong.ai.utiltest.resultjsonparase.config; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +/** + *

主表

+ * + *

create: 2023/7/3 11:23

+ * + * @author youHong.ai + */ +@Setter +@Getter +@ToString +public class MainTable { +// 一堆其他配置字段.... + + private Integer id; + + /** 配置映射 */ + private List mappings; + + /** 别名映射 */ + private List aliasesList; +}