diff --git a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioService.java b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioService.java index c99596c..96a9acd 100644 --- a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioService.java +++ b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioService.java @@ -267,7 +267,7 @@ public class UrkMinioService { public List getFileBast64List(String id, String sourceId, String sourceTable, String sourceType) throws Exception { List list=mapper.getFileList(id,sourceId,sourceType,sourceTable); for (UploadFileVo vo:list){ - String bast64=minioUtils.getMinioBast64(vo.getBucketName(),vo.getFilePath()); + String bast64=minioUtils.getMinioFileCompress(vo.getBucketName(),vo.getFilePath()); vo.setBast64(bast64); } return list; diff --git a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioUtil.java b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioUtil.java index 325d876..c3a14e8 100644 --- a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioUtil.java +++ b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/minio/UrkMinioUtil.java @@ -2,6 +2,7 @@ package com.bonus.urk.minio; import com.bonus.system.api.domain.SysFile; +import com.bonus.urk.vo.ImageResizer; import io.minio.*; import io.minio.errors.MinioException; import io.minio.http.Method; @@ -303,7 +304,6 @@ public class UrkMinioUtil { while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } - byte[] bytes = outputStream.toByteArray(); String bast64= Base64.getEncoder().encodeToString(bytes); inputStream.close(); @@ -311,6 +311,24 @@ public class UrkMinioUtil { return bast64; } + + @SneakyThrows(Exception.class) + public String getMinioFileCompress(String bucketName,String path) { + InputStream inputStream= minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(path).build()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + byte[] bytes = outputStream.toByteArray(); + // + String bast64=ImageResizer.transImageByJpg(bytes); + inputStream.close(); + outputStream.close(); + return bast64; + } + /** * 删除文件 * diff --git a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/IdUtils.java b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/IdUtils.java new file mode 100644 index 0000000..4dc6de8 --- /dev/null +++ b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/IdUtils.java @@ -0,0 +1,60 @@ +package com.bonus.urk.vo; + +/** + * ID生成器工具类 + * + * @author czc + */ +public class IdUtils +{ + /** + * 获取随机UUID + * + * @return 随机UUID + */ + public static String randomuuid() + { + return UUID.randomuuid().toString(); + } + + /** + * 简化的UUID,去掉了横线 + * + * @return 简化的UUID,去掉了横线 + */ + public static String simpleuuid() + { + return UUID.randomuuid().toString(true); + } + + + /** + * 简化的UUID,去掉了横线 + * + * @return 简化的UUID,去掉了横线 + */ + public static String getuid() + { + return UUID.randomuuid().toString(true).toUpperCase(); + } + + /** + * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 随机UUID + */ + public static String fastuuid() + { + return UUID.fastuuid().toString(); + } + + /** + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 简化的UUID,去掉了横线 + */ + public static String fastsimpleuuid() + { + return UUID.fastuuid().toString(true); + } +} diff --git a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/ImageResizer.java b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/ImageResizer.java new file mode 100644 index 0000000..1bd00a0 --- /dev/null +++ b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/ImageResizer.java @@ -0,0 +1,160 @@ +package com.bonus.urk.vo; + +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +@Slf4j +public class ImageResizer { + + + + public static List fileType = new ArrayList<>(); + + + /** + * 获取文件->最终转成 本地临时文件、使用完必须删除 + * @param + * @return + */ + public static String transImageByJpg(byte[] bytes){ + try{ + String suffix=".jpg"; + long timestamp1 = System.currentTimeMillis(); + String filePath=getZipPath()+timestamp1; + createDirectories(filePath); + String roundId=IdUtils.randomuuid(); + String path="/temp/"; + File folder = new File(filePath+path); + if (folder.exists() && folder.isDirectory()) { + System.out.println("文件夹存在"); + } else { + folder.mkdir(); + System.out.println("文件夹不存在"); + } + // 创建临时文件,确保文件名具有唯一性 + File file = File.createTempFile(filePath+path+roundId, suffix); + // 将字节数据写入文件 + FileOutputStream fos = new FileOutputStream(file); + fos.write(bytes); + fos.close(); + String newJpgPath=null; + //不是jpg的先转成jpg的 + getFileType(); + if (!fileType.contains(suffix)){ + String roundId2=IdUtils.randomuuid(); + //jpg的路径 + newJpgPath=filePath+path+roundId2+".jpg"; + BufferedImage pngImage = ImageIO.read(file); + BufferedImage jpgImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB); + // 绘制PNG图片到jpgImage + jpgImage.createGraphics().drawImage(pngImage, 0, 0, Color.WHITE, null); + ImageIO.write(jpgImage, "jpg", new File(newJpgPath)); + } + // + File inputFile; + //是jpg格式的 + if(newJpgPath==null){ + inputFile=file; + }else{ + inputFile = new File(newJpgPath); + } + BufferedImage originalImage = ImageIO.read(inputFile); + BufferedImage resizedImage = resizeImage(originalImage, 1080, 800); + // 保存为PNG格式 + String roundId3=IdUtils.randomuuid(); + String lastPath=filePath+path+roundId3+".jpg"; + saveImage(resizedImage, "jpg", lastPath); + if(newJpgPath!=null){ + boolean isde=new File(newJpgPath).delete(); + System.err.println("删除->"+isde); + } + boolean delete=file.delete(); + System.err.println("删除->"+delete); + + // 读取文件内容 + byte[] fileContent = Files.readAllBytes(Paths.get(lastPath)); + // 编码为Base64 + String base64Encoded = Base64.getEncoder().encodeToString(fileContent); + deleteDirectoryContents(filePath); + return base64Encoded; + }catch (Exception e){ + log.error(e.toString(),e); + } + return null; + } + + //文件 + public static boolean createDirectories(String path) { + Path dir = Paths.get(path); + try { + return Files.createDirectories(dir).isAbsolute(); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + return false; + } + public static void deleteDirectoryContents(String path) { + try { + Path directory = Paths.get(path); + Files.walkFileTree(directory, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } + public static String getZipPath(){ + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("win")) { + return "F:\\temp\\"; + } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) { + return "/data/local/tmp/"; + } else { + return "/data/local/tmp/"; + } + + } + + + public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) { + BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType()); + Graphics2D graphics2D = resizedImage.createGraphics(); + graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); + graphics2D.dispose(); + return resizedImage; + } + + public static void saveImage(BufferedImage resizedImage, String format, String outputPath) throws IOException { + File outputFile = new File(outputPath); + ImageIO.write(resizedImage, format, outputFile); + } + + public static void getFileType(){ + fileType.add("jpg"); + fileType.add("JPG"); + fileType.add(".JPG"); + fileType.add(".jpg"); + + } +} \ No newline at end of file diff --git a/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/UUID.java b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/UUID.java new file mode 100644 index 0000000..aa925e5 --- /dev/null +++ b/bonus-modules/bonus-urk/src/main/java/com/bonus/urk/vo/UUID.java @@ -0,0 +1,490 @@ +package com.bonus.urk.vo; + + + +import com.sun.xml.internal.ws.util.UtilException; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 提供通用唯一识别码(universally unique identifier)(UUID)实现 + * + * @author czc + */ +public final class UUID implements java.io.Serializable, Comparable +{ + private static final long serialVersionUID = -1185015143654744140L; + + /** + * SecureRandom 的单例 + * + */ + private static class Holder + { + static final SecureRandom NUMBER_GENERATOR= getSecureRandom(); + } + + /** 此UUID的最高64有效位 */ + private final long mostSigBits; + + /** 此UUID的最低64有效位 */ + private final long leastSigBits; + + /** + * 私有构造 + * + * @param data 数据 + */ + private UUID(byte[] data) + { + long msb = 0; + long lsb = 0; + int max=8; + int max1=16; + assert data.length == 16 : "data must be 16 bytes in length"; + for (int i = 0; i < max; i++) + { + msb = (msb << max) | (data[i] & 0xff); + } + for (int i = max; i < max1; i++) + { + lsb = (lsb << max) | (data[i] & 0xff); + } + this.mostSigBits = msb; + this.leastSigBits = lsb; + } + + /** + * 使用指定的数据构造新的 UUID。 + * + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 + */ + public UUID(long mostSigBits, long leastSigBits) + { + this.mostSigBits = mostSigBits; + this.leastSigBits = leastSigBits; + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID fastuuid() + { + return randomuuid(false); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID randomuuid() + { + return randomuuid(true); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 + * @return 随机生成的 {@code UUID} + */ + public static UUID randomuuid(boolean isSecure) + { + final Random ng = isSecure ? Holder.NUMBER_GENERATOR : getRandom(); + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; + randomBytes[6] |= 0x40; + randomBytes[8] &= 0x3f; + randomBytes[8] |= 0x80; + return new UUID(randomBytes); + } + + /** + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 + * + * @param name 用于构造 UUID 的字节数组。 + * + * @return 根据指定数组生成的 {@code UUID} + */ + public static UUID nameuuidfrombytes(byte[] name) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException nsae) + { + throw new InternalError("MD5 not supported"); + } + byte[] md5Bytes = md.digest(name); + md5Bytes[6] &= 0x0f; + md5Bytes[6] |= 0x30; + md5Bytes[8] &= 0x3f; + md5Bytes[8] |= 0x80; + return new UUID(md5Bytes); + } + + /** + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 + * + * @param name 指定 {@code UUID} 字符串 + * @return 具有指定值的 {@code UUID} + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 + * + */ + public static UUID fromString(String name) + { + String[] components = name.split("-"); + int len5=5; + if (components.length != len5) + { + throw new IllegalArgumentException("Invalid UUID string: " + name); + } + StringBuilder scrub=new StringBuilder("0x"); + for (int i = 0; i < len5; i++) + { + components[i] =scrub.append(components[i]).toString(); + } + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new UUID(mostSigBits, leastSigBits); + } + + /** + * 返回此 UUID 的 128 位值中的最低有效 64 位。 + * + * @return 此 UUID 的 128 位值中的最低有效 64 位。 + */ + public long getLeastSignificantBits() + { + return leastSigBits; + } + + /** + * 返回此 UUID 的 128 位值中的最高有效 64 位。 + * + * @return 此 UUID 的 128 位值中最高有效 64 位。 + */ + public long getMostSignificantBits() + { + return mostSigBits; + } + + /** + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 + *

+ * 版本号具有以下含意: + *

    + *
  • 1 基于时间的 UUID + *
  • 2 DCE 安全 UUID + *
  • 3 基于名称的 UUID + *
  • 4 随机生成的 UUID + *
+ * + * @return 此 {@code UUID} 的版本号 + */ + public int version() + { + // Version is bits masked by 0x000000000000F000 in MS long + return (int) ((mostSigBits >> 12) & 0x0f); + } + + /** + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 + *

+ * 变体号具有以下含意: + *

    + *
  • 0 为 NCS 向后兼容保留 + *
  • 2 IETF RFC 4122(Leach-Salz), 用于此类 + *
  • 6 保留,微软向后兼容 + *
  • 7 保留供以后定义使用 + *
+ * + * @return 此 {@code UUID} 相关联的变体号 + */ + public int variant() + { + // This field is composed of a varying number of bits. + // 0 - - Reserved for NCS backward compatibility + // 1 0 - The IETF aka Leach-Salz variant (used by this class) + // 1 1 0 Reserved, Microsoft backward compatibility + // 1 1 1 Reserved for future definition. + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); + } + + /** + * 与此 UUID 相关联的时间戳值。 + * + *

+ * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。
+ * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 + * + *

+ * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 + */ + public long timestamp() throws UnsupportedOperationException + { + checkTimeBase(); + return (mostSigBits & 0x0FFFL) << 48 + | ((mostSigBits >> 16) & 0x0FFFFL) << 32 + | mostSigBits >>> 32; + } + + /** + * 与此 UUID 相关联的时钟序列值。 + * + *

+ * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 + *

+ * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 + * UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的时钟序列 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public int clockSequence() throws UnsupportedOperationException + { + checkTimeBase(); + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + + /** + * 与此 UUID 相关的节点值。 + * + *

+ * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 + *

+ * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的节点值 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public long node() throws UnsupportedOperationException + { + checkTimeBase(); + return leastSigBits & 0x0000FFFFFFFFFFFFL; + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @return 此{@code UUID} 的字符串表现形式 + * @see #toString(boolean) + */ + @Override + public String toString() + { + return toString(false); + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 + * @return 此{@code UUID} 的字符串表现形式 + */ + public String toString(boolean isSimple) + { + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); + // time_low + builder.append(digits(mostSigBits >> 32, 8)); + if (false == isSimple) + { + builder.append('-'); + } + // time_mid + builder.append(digits(mostSigBits >> 16, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // time_high_and_version + builder.append(digits(mostSigBits, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // variant_and_sequence + builder.append(digits(leastSigBits >> 48, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // node + builder.append(digits(leastSigBits, 12)); + + return builder.toString(); + } + + /** + * 返回此 UUID 的哈希码。 + * + * @return UUID 的哈希码值。 + */ + @Override + public int hashCode() + { + long hilo = mostSigBits ^ leastSigBits; + return ((int) (hilo >> 32)) ^ (int) hilo; + } + + /** + * 将此对象与指定对象比较。 + *

+ * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 + * + * @param obj 要与之比较的对象 + * + * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} + */ + @Override + public boolean equals(Object obj) + { + if ((null == obj) || (obj.getClass() != UUID.class)) + { + return false; + } + UUID id = (UUID) obj; + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); + } + + // Comparison Operations + + /** + * 将此 UUID 与指定的 UUID 比较。 + * + *

+ * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 + * + * @param val 与此 UUID 比较的 UUID + * + * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 + * + */ + @Override + public int compareTo(UUID val) + { + // The ordering is intentionally set up so that the UUIDs + // can simply be numerically compared as two numbers + return (this.mostSigBits < val.mostSigBits ? -1 : + (this.mostSigBits > val.mostSigBits ? 1 : + (this.leastSigBits < val.leastSigBits ? -1 : + (this.leastSigBits > val.leastSigBits ? 1 : + 0)))); + } + + // ------------------------------------------------------------------------------------------------------------------- + // Private method start + /** + * 返回指定数字对应的hex值 + * + * @param val 值 + * @param digits 位 + * @return 值 + */ + private static String digits(long val, int digits) + { + long hi = 1L << (digits * 4); + return Long.toHexString(hi | (val & (hi - 1))).substring(1); + } + + /** + * 检查是否为time-based版本UUID + */ + private void checkTimeBase() + { + if (version() != 1) + { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + } + + /** + * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) + * + * @return {@link SecureRandom} + */ + public static SecureRandom getSecureRandom() + { + try + { + return SecureRandom.getInstance("SHA1PRNG"); + } + catch (NoSuchAlgorithmException e) + { + throw new UtilException(e); + } + } + + /** + * 获取随机数生成器对象
+ * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 + * + * @return {@link ThreadLocalRandom} + */ + public static ThreadLocalRandom getRandom() + { + return ThreadLocalRandom.current(); + } +}