From cfccb4ebe87c24f135cf60145509c21209d76a10 Mon Sep 17 00:00:00 2001 From: XuYijie <1119461672@qq.com> Date: Thu, 23 Nov 2023 17:12:52 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=98=8A1.3.3=E7=89=88=E6=9C=AC=E5=8F=91?= =?UTF-8?q?=E5=B8=83=201=E3=80=81=E6=94=AF=E6=8C=81=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E7=B1=BB=E5=9E=8B=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=202=E3=80=81=E5=BC=95=E5=85=A5=E4=BA=86tika?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=8E=E6=96=87=E4=BB=B6=E5=AD=97=E8=8A=82?= =?UTF-8?q?=E4=B8=AD=E8=8E=B7=E5=8F=96=E6=96=87=E4=BB=B6=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++-- pom.xml | 7 +- .../base64utils/Base64FileTypeEnum.java | 83 +++++++++++++++++-- .../icu/xuyijie/base64utils/Base64Utils.java | 71 ++++++++++++---- 4 files changed, 144 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ff11d55..6d54439 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,23 @@ icu.xuyijie Base64Utils - 1.3.2 + 1.3.3 ``` - 使用 ```java // 将文件编码成Base64,可传入文件全路径,或者一个 File 对象,第二个参数是是否生成前缀 -String s = Base64Util.transferToBase64("D:/下载/Screenshot_20221008-090627.png", false); +String s = Base64Utils.transferToBase64("D:/下载/Screenshot_20221008-090627.png", false); File file = new File(filePath); -String s = Base64Util.transferToBase64(file, false); +String s = Base64Utils.transferToBase64(file, false); System.out.println(s); // 将Base64转换成文件保存到指定位置,可传入文件全路径或者分别传入保存位置和文件名,路径分隔符可使用/或\ -String s1 = Base64Util.generateFile(s, "D:\\下载\\aaa.png"); -String s1 = Base64Util.generateFile(s, "D:/下载", "aaa.png"); +String s1 = Base64Utils.generateFile(s, "D:\\下载\\aaa.png"); +String s1 = Base64Utils.generateFile(s, "D:/下载", "aaa.png"); System.out.println(s1); -//也可以从base64获取文件对象呵呵流,或者文件类型 -File file = Base64Util.getFile("D:/下载/a.png"); -FileInputStream fileInputStream = Base64Util.getFileStream("D:/下载/a.png"); -String fileType = Base64Util.getFileType("base64Str"); +//也可以从base64获取文件对象流,或者文件类型 +File file = Base64Utils.getFile("D:/下载/a.png"); +FileInputStream fileInputStream = Base64Utils.getFileStream("D:/下载/a.png"); +String fileType = Base64Utils.getFileType("传入base64Str"); ``` diff --git a/pom.xml b/pom.xml index 5267724..0438d99 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 icu.xuyijie Base64Utils - 1.3.2 + 1.3.3 Base64Utils 将 Base64 解码生成文件保存到指定路径,或将文件转换成 Base64 码 https://github.com/BubblingXuYijie/Base64Util @@ -49,6 +49,11 @@ commons-lang3 3.13.0 + + org.apache.tika + tika-core + 2.9.1 + diff --git a/src/main/java/icu/xuyijie/base64utils/Base64FileTypeEnum.java b/src/main/java/icu/xuyijie/base64utils/Base64FileTypeEnum.java index cf096b3..1c93423 100644 --- a/src/main/java/icu/xuyijie/base64utils/Base64FileTypeEnum.java +++ b/src/main/java/icu/xuyijie/base64utils/Base64FileTypeEnum.java @@ -9,40 +9,105 @@ * @description base64特殊前缀对应文件类型 */ public enum Base64FileTypeEnum { - // 文件类型 + // 文档文件 DOC(".doc", "data:application/msword;base64,"), DOCX(".docx", "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,"), XLS(".xls", "data:application/vnd.ms-excel;base64,"), XLSX(".xlsx", "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,"), + CSV(".csv", "data:text/csv;base64,"), PDF(".pdf", "data:application/pdf;base64,"), PPT(".ppt", "data:application/vnd.ms-powerpoint;base64,"), PPTX(".pptx", "data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,"), - JSON(".json", "data:application/json;base64,"), - TXT(".txt", "data:text/plain;base64,"), + SWF(".swf", "data:application/x-shockwave-flash;base64,"), + PSD(".psd", "data:image/vnd.adobe.photoshop;base64,"), + + //安装包 + MSI(".msi", "data:application/x-ms-installer;base64,"), EXE(".exe", "data:application/x-msdownload;base64,"), - ZIP(".zip", "data:application/x-zip-compressed;base64,"), + EXE2(".exe", "data:application/x-dosexec;base64,"), + MPKG(".mpkg", "data:application/vnd.apple.installer+xml;base64,"), + + //压缩文件 + ZIP(".zip", "data:application/zip;base64,"), + ZIP2(".zip", "data:application/x-zip-compressed;base64,"), + SEVEN_Z(".7z", "data:application/x-7z-compressed;base64,"), + RAR(".rar", "data:application/x-rar-compressed;base64,"), //还可能是7z、tar.bz、tar.xz,不过没关系,就返回rar就行了,因为这些文件类型修改为rar也可以正常解压 - RAR(".rar", "data:application/x-compressed;base64,"), + RAR2(".rar", "data:application/x-compressed;base64,"), TAR(".tar", "data:application/x-tar;base64,"), TAR_GZ(".tar.gz", "data:application/x-gzip;base64,"), + BZ(".bz", "data:application/x-bzip;base64,"), + BZ2(".bz2", "data:application/x-bzip2;base64,"), + JAR(".jar", "data:application/java-archive;base64,"), + + //文本类型 + TXT(".txt", "data:text/plain;base64,"), + JSON(".json", "data:application/json;base64,"), + MD(".md", "data:text/x-web-markdown;base64,"), + SQL(".sql", "data:text/x-sql;base64,"), + JS(".js", "data:text/javascript;base64,"), + JS2(".js", "data:application/javascript;base64,"), + CSS(".css", "data:text/css;base64,"), + HTML(".html", "data:text/html;base64,"), + XHTML(".xhtml", "data:application/xhtml+xml;base64,"), + XML(".xml", "data:application/xml;base64,"), + XML2(".xml", "data:text/xml;base64,"), + C(".c", "data:text/x-csrc;base64,"), + CS(".cs", "data:text/x-csharp;base64,"), + RS(".rs", "data:application/rls-services+xml;base64,"), + PY(".py", "data:text/x-python;base64,"), + PHP(".php", "data:text/x-php;base64,"), + JAVA(".java", "data:text/x-java-source;base64,"), + JAVA_PROPERTIES(".properties", "data:text/x-java-properties;base64,"), + YAML(".yml", "data:text/x-yaml;base64,"), + SH(".sh", "data:application/x-sh;base64,"), + CSH(".csh", "data:application/x-csh;base64,"), + BAT(".bat", "data:application/x-bat;base64,"), + AZW(".azw", "data:application/vnd.amazon.ebook;base64,"), + EPUB(".epub", "data:application/epub+zip;base64,"), //音频类型 + WEBA(".weba", "data:audio/webm;base64,"), + THREE_GP_A(".3gp", "data:audio/3gpp;base64,"), + THREE_GP_A2(".3g2", "data:audio/3gpp2;base64,"), MP3(".mp3", "data:audio/mpeg;base64,"), + AAC(".aac", "data:audio/aac;base64,"), + WAV(".wav", "data:audio/wav;base64,"), + WAV2(".wav", "data:audio/x-wav;base64,"), + M4A(".m4a", "data:audio/mp4;base64,"), //视频类型 + WEBM(".webm", "data:video/webm;base64,"), + THREE_GP_V(".3gp", "data:video/3gpp;base64,"), + THREE_GP_V2(".3g2", "data:video/3gpp2;base64,"), + AVI(".avi", "data:video/x-msvideo;base64,"), MP4(".mp4", "data:video/mp4;base64,"), + MPEG(".mpeg", "data:video/mpeg;base64,"), + FLV(".flv", "data:video/x-flv;base64,"), + MKV(".mkv", "data:video/x-matroska;base64,"), + RMVB(".rmvb", "data:application/vnd.rn-realmedia-vbr;base64,"), // 图片类型 + WEBP(".webp", "data:image/webp;base64,"), PNG(".png", "data:image/png;base64,"), - JPG(".jpg", "data:image/jpeg;base64,"), - JPEG(".jpeg", "data:image/jpeg;base64,"), + JPG(".jpg", "data:image/jpg;base64,"), + JPEG(".jpg", "data:image/jpeg;base64,"), GIF(".gif", "data:image/gif;base64,"), SVG(".svg", "data:image/svg+xml;base64,"), ICO(".ico", "data:image/x-icon;base64,"), + ICO2(".ico", "data:image/vnd.microsoft.icon;base64,"), BMP(".bmp", "data:image/bmp;base64,"), + TIFF(".tiff", "data:image/tiff;base64,"), + + //字体文件 + TTF(".ttf", "data:font/ttf;base64,"), + WOFF(".woff", "data:font/woff;base64,"), + WOFF1(".woff", "data:application/x-font-woff;base64,"), + WOFF2(".woff2", "data:font/woff2;base64,"), + EOT(".eot", "data:application/vnd.ms-fontobject;base64,"), - // 二进制流,这种前缀可能是rar、heic图片、md文件、sql文件等等,无法判断文件类型,随便指定一个 - OCTET_STREAM(".rar", "data:application/octet-stream;base64,"), + // 未知类型,这种前缀可能是rar、heic图片、md文件等等,无法判断文件类型,返回二进制文件吧 + OCTET_STREAM(".bin", "data:application/octet-stream;base64,"), ; Base64FileTypeEnum(String type, String prefix) { diff --git a/src/main/java/icu/xuyijie/base64utils/Base64Utils.java b/src/main/java/icu/xuyijie/base64utils/Base64Utils.java index 19d7958..7ba0b5d 100644 --- a/src/main/java/icu/xuyijie/base64utils/Base64Utils.java +++ b/src/main/java/icu/xuyijie/base64utils/Base64Utils.java @@ -1,6 +1,7 @@ package icu.xuyijie.base64utils; import org.apache.commons.lang3.StringUtils; +import org.apache.tika.Tika; import java.io.*; import java.nio.file.Files; @@ -30,6 +31,7 @@ * FileInputStream fileInputStream1 = Base64Util.getFileStream("D:/下载/a.png"); * String fileType = Base64Util.getFileType("base64Str"); */ +@SuppressWarnings("unused") public class Base64Utils { private Base64Utils() { @@ -136,39 +138,76 @@ public static String getNoPrefixBase64(String base64Str) { * @return 文件类型 */ public static String getFileType(String base64Str) { - String fileType; + String fileType = ""; //从未处理过的base64码中判断文件类型 String base64Prefix = StringUtils.substringBetween(base64Str, "/", BASE64_PREFIX_SUBSTRING); if (StringUtils.isEmpty(base64Prefix)) { - fileType = ".png"; - logger.log(Level.WARNING, "传入的base64没有前缀,并且传入的文件名没有扩展名,所以无法确定文件类型,默认png格式"); + //如果没有前缀,采用Tika读取文件字节进行判断 + File file = decodeBase64ToFile(base64Str, ""); + if (file != null) { + String fileMimeType = getFileMimeType(file); + fileType = Base64FileTypeEnum.getFileType(fileMimeType); + } else { + logger.log(Level.WARNING, "无法确定文件类型"); + } } else { - //做文件后缀名检测,因为base64的一个缺点就是后缀名不能自动生成,有些特殊后缀无法直接获取 + //根据base64前缀获取文件类型 fileType = Base64FileTypeEnum.getFileType(base64Prefix); } return fileType; } /** - * base64转为文件对象 + * 解析文件对象获取文件mimeType * - * @param base64Str base64 - * @return 文件流对象 + * @param file 文件对象 + * @return 文件mimeType */ - public static File getFile(String base64Str) { + public static String getFileMimeType(File file) { + Tika tika = new Tika(); + try { + return tika.detect(file); + } catch (IOException e) { + return ""; + } + } + + /** + * 从base64字符串中解析出临时文件对象 + * + * @param base64NoPrefix base64字符串(无前缀) + * @param fileType 文件类型扩展名 + * @return 临时文件对象 + */ + private static File decodeBase64ToFile(String base64NoPrefix, String fileType) { + File tempFile = null; + // Base64解码 + byte[] bytes = decodeBase64ToByte(base64NoPrefix); try { - String fileType = getFileType(base64Str); - String base64NoPrefix = getNoPrefixBase64(base64Str); - // Base64解码 - byte[] bytes = decodeBase64(base64NoPrefix); // 生成临时文件 - File tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), fileType); + tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), fileType); try (BufferedOutputStream out = new BufferedOutputStream(Files.newOutputStream(tempFile.toPath()))) { out.write(bytes); out.flush(); } tempFile.deleteOnExit(); - return tempFile; + } catch (IOException e) { + logger.log(Level.WARNING, "base64转换文件对象失败", e); + } + return tempFile; + } + + /** + * base64转为文件对象 + * + * @param base64Str base64 + * @return 文件流对象 + */ + public static File getFile(String base64Str) { + try { + String fileType = getFileType(base64Str); + String base64NoPrefix = getNoPrefixBase64(base64Str); + return decodeBase64ToFile(base64NoPrefix, fileType); } catch (Exception e) { logger.log(Level.WARNING, "base64转换文件对象失败——", e); } @@ -202,7 +241,7 @@ public static FileInputStream getFileStream(String base64Str) { private static void saveFile(String base64NoPrefix, String filePath) { try { // Base64解码 - byte[] bytes = decodeBase64(base64NoPrefix); + byte[] bytes = decodeBase64ToByte(base64NoPrefix); // 生成文件 try (BufferedOutputStream out = new BufferedOutputStream(Files.newOutputStream(Paths.get(filePath)))) { out.write(bytes); @@ -219,7 +258,7 @@ private static void saveFile(String base64NoPrefix, String filePath) { * @param base64Str Base64 * @return 字节数组 */ - private static byte[] decodeBase64(String base64Str) { + private static byte[] decodeBase64ToByte(String base64Str) { // Base64解码 byte[] bytes = Base64.getDecoder().decode(base64Str); for (int i = 0; i < bytes.length; ++i) {