diff --git a/CHANGELOG.md b/CHANGELOG.md index e7055c2ca..d442f4958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,15 @@ ------------------------------------------------------------------------------------------------------------- -## 5.3.6 (2020-05-17) +## 5.3.6 (2020-05-19) ### 新特性 * 【core 】 NumberConverter Long类型增加日期转换(pr#872@Github) * 【all 】 StrUtil and SymmetricCrypto注释修正(pr#873@Github) * 【core 】 CsvReader支持返回Bean(issue#869@Github) * 【core 】 Snowflake循环等待下一个时间时避免长时间循环,加入对时钟倒退的判断(pr#874@Github) +* 【extra 】 新增 QRCode base64 编码形式返回(pr#878@Github) +* 【core 】 ImgUtil增加toBase64DateUri,URLUtil增加getDataUri方法 ### Bug修复 diff --git a/hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java b/hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java index 21bbcdb61..74d0faaa1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java @@ -13,6 +13,7 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; import javax.imageio.IIOImage; import javax.imageio.ImageIO; @@ -1261,6 +1262,20 @@ public class ImgUtil { return IoUtil.toStream(toBytes(image, imageType)); } + /** + * 将图片对象转换为Base64的Data URI形式,格式为:data:image/[imageType];base64,[data] + * + * @param image 图片对象 + * @param imageType 图片类型 + * @return Base64的字符串表现形式 + * @since 5.3.6 + */ + public static String toBase64DateUri(Image image, String imageType) { + return URLUtil.getDataUri( + "image/" + imageType, "base64", + toBase64(image, imageType)); + } + /** * 将图片对象转换为Base64形式 * diff --git a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java index 62359ef8a..989c89acb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java @@ -28,7 +28,16 @@ import java.util.Map; import java.util.jar.JarFile; /** - * 统一资源定位符相关工具类 + * URL(Uniform Resource Locator)统一资源定位符相关工具类 + * + *
+ * 统一资源定位符,描述了一台特定服务器上某资源的特定位置。 + *
+ * URL组成: + *+ * 协议://主机名[:端口]/ 路径/[:参数] [?查询]#Fragment + * protocol :// hostname[:port] / path / [:parameters][?query]#fragment + ** * @author xiaoleilu */ @@ -749,11 +758,11 @@ public class URLUtil { * @throws IORuntimeException IO异常 * @since 5.3.4 */ - public static long getContentLength(URL url) throws IORuntimeException{ - if(null == url){ + public static long getContentLength(URL url) throws IORuntimeException { + if (null == url) { return -1; } - + URLConnection conn = null; try { conn = url.openConnection(); @@ -762,8 +771,61 @@ public class URLUtil { throw new IORuntimeException(e); } finally { if (conn instanceof HttpURLConnection) { - ((HttpURLConnection)conn).disconnect(); + ((HttpURLConnection) conn).disconnect(); } } } + + /** + * Data URI Scheme封装。data URI scheme 允许我们使用内联(inline-code)的方式在网页中包含数据,
+ * Data URI的格式规范: + *
+ * data:[+ * + * @param mimeType 可选项(null表示无),数据类型(image/png、text/plain等) + * @param encoding 数据编码方式(US-ASCII,BASE64等) + * @param data 编码后的数据 + * @return Data URI字符串 + * @since 5.3.6 + */ + public static String getDataUri(String mimeType, String encoding, String data){ + return getDataUri(mimeType, null, encoding, data); + } + + /** + * Data URI Scheme封装。data URI scheme 允许我们使用内联(inline-code)的方式在网页中包含数据,][;charset= ][; ], + *
+ * Data URI的格式规范: + *
+ * data:[+ * + * @param mimeType 可选项(null表示无),数据类型(image/png、text/plain等) + * @param charset 可选项(null表示无),源文本的字符集编码方式 + * @param encoding 数据编码方式(US-ASCII,BASE64等) + * @param data 编码后的数据 + * @return Data URI字符串 + * @since 5.3.6 + */ + public static String getDataUri(String mimeType, Charset charset, String encoding, String data){ + final StringBuilder builder = StrUtil.builder("data:"); + if(StrUtil.isNotBlank(mimeType)){ + builder.append(mimeType); + } + if(null != charset){ + builder.append(";charset=").append(charset.name()); + } + if(StrUtil.isNotBlank(encoding)){ + builder.append(';').append(encoding); + } + builder.append(',').append(data); + + return builder.toString(); + } } \ No newline at end of file diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java index 735f43766..f0cee3c74 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java @@ -1,5 +1,6 @@ package cn.hutool.extra.qrcode; +import cn.hutool.core.codec.Base64; import cn.hutool.core.img.Img; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.util.CharsetUtil; @@ -19,24 +20,17 @@ import com.google.zxing.common.HybridBinarizer; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.text.MessageFormat; -import java.util.Base64; import java.util.HashMap; -import javax.imageio.ImageIO; - /** * 基于Zxing的二维码工具类 - * + * * @author looly * @since 4.0.2 - * */ public class QrCodeUtil { @@ -50,13 +44,7 @@ public class QrCodeUtil { * @return 图片 Base64 编码字符串 */ public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, String logoBase64) { - byte[] decode; - try { - decode = Base64.getDecoder().decode(logoBase64); - } catch (Exception e) { - throw new QrCodeException(e); - } - return generateAsBase64(content, qrConfig, imageType, decode); + return generateAsBase64(content, qrConfig, imageType, Base64.decode(logoBase64)); } /** @@ -69,36 +57,46 @@ public class QrCodeUtil { * @return 图片 Base64 编码字符串 */ public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, byte[] logo) { - BufferedImage img; - try { - img = ImageIO.read(new ByteArrayInputStream(logo)); - } catch (IOException e) { - throw new QrCodeException(e); - } - qrConfig.setImg(img); + return generateAsBase64(content, qrConfig, imageType, ImgUtil.toImage(logo)); + } + + /** + * 生成代 logo 图片的 Base64 编码格式的二维码,以 String 形式表示 + * + * @param content 内容 + * @param qrConfig 二维码配置,包括长、宽、边距、颜色等 + * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} + * @param logo logo 图片的byte[] + * @return 图片 Base64 编码字符串 + */ + public static String generateAsBase64(String content, QrConfig qrConfig, String imageType, Image logo) { + qrConfig.setImg(logo); return generateAsBase64(content, qrConfig, imageType); } /** * 生成 Base64 编码格式的二维码,以 String 形式表示 * + *][;charset= ][; ], + *
+ * 输出格式为: data:image/[type];base64,[data] + *
+ * * @param content 内容 * @param qrConfig 二维码配置,包括长、宽、边距、颜色等 * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} * @return 图片 Base64 编码字符串 */ public static String generateAsBase64(String content, QrConfig qrConfig, String imageType) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - generate(content, qrConfig, imageType, bos); - byte[] encode = Base64.getEncoder().encode(bos.toByteArray()); - return MessageFormat.format("data:image/{0};base64,{1}", imageType, new String(encode)); + final BufferedImage img = generate(content, qrConfig); + return ImgUtil.toBase64DateUri(img, imageType); } + /** * 生成PNG格式的二维码图片,以byte[]形式表示 * * @param content 内容 - * @param width 宽度 - * @param height 高度 + * @param width 宽度 + * @param height 高度 * @return 图片的byte[] * @since 4.0.10 */ @@ -112,7 +110,7 @@ public class QrCodeUtil { * 生成PNG格式的二维码图片,以byte[]形式表示 * * @param content 内容 - * @param config 二维码配置,包括长、宽、边距、颜色等 + * @param config 二维码配置,包括长、宽、边距、颜色等 * @return 图片的byte[] * @since 4.1.2 */ @@ -124,10 +122,10 @@ public class QrCodeUtil { /** * 生成二维码到文件,二维码图片格式取决于文件的扩展名 - * - * @param content 文本内容 - * @param width 宽度 - * @param height 高度 + * + * @param content 文本内容 + * @param width 宽度 + * @param height 高度 * @param targetFile 目标文件,扩展名决定输出格式 * @return 目标文件 */ @@ -139,9 +137,9 @@ public class QrCodeUtil { /** * 生成二维码到文件,二维码图片格式取决于文件的扩展名 - * - * @param content 文本内容 - * @param config 二维码配置,包括长、宽、边距、颜色等 + * + * @param content 文本内容 + * @param config 二维码配置,包括长、宽、边距、颜色等 * @param targetFile 目标文件,扩展名决定输出格式 * @return 目标文件 * @since 4.1.2 @@ -154,12 +152,12 @@ public class QrCodeUtil { /** * 生成二维码到输出流 - * - * @param content 文本内容 - * @param width 宽度 - * @param height 高度 + * + * @param content 文本内容 + * @param width 宽度 + * @param height 高度 * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} - * @param out 目标流 + * @param out 目标流 */ public static void generate(String content, int width, int height, String imageType, OutputStream out) { final BufferedImage image = generate(content, width, height); @@ -168,11 +166,11 @@ public class QrCodeUtil { /** * 生成二维码到输出流 - * - * @param content 文本内容 - * @param config 二维码配置,包括长、宽、边距、颜色等 + * + * @param content 文本内容 + * @param config 二维码配置,包括长、宽、边距、颜色等 * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} - * @param out 目标流 + * @param out 目标流 * @since 4.1.2 */ public static void generate(String content, QrConfig config, String imageType, OutputStream out) { @@ -182,10 +180,10 @@ public class QrCodeUtil { /** * 生成二维码图片 - * + * * @param content 文本内容 - * @param width 宽度 - * @param height 高度 + * @param width 宽度 + * @param height 高度 * @return 二维码图片(黑白) */ public static BufferedImage generate(String content, int width, int height) { @@ -194,11 +192,11 @@ public class QrCodeUtil { /** * 生成二维码或条形码图片 - * + * * @param content 文本内容 - * @param format 格式,可选二维码或者条形码 - * @param width 宽度 - * @param height 高度 + * @param format 格式,可选二维码或者条形码 + * @param width 宽度 + * @param height 高度 * @return 二维码图片(黑白) */ public static BufferedImage generate(String content, BarcodeFormat format, int width, int height) { @@ -207,9 +205,9 @@ public class QrCodeUtil { /** * 生成二维码图片 - * + * * @param content 文本内容 - * @param config 二维码配置,包括长、宽、边距、颜色等 + * @param config 二维码配置,包括长、宽、边距、颜色等 * @return 二维码图片(黑白) * @since 4.1.2 */ @@ -220,10 +218,10 @@ public class QrCodeUtil { /** * 生成二维码或条形码图片