Browse Source

add methods

Looly 5 years ago
parent
commit
4b53701670

+ 3 - 1
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修复
 

+ 15 - 0
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;
@@ -1262,6 +1263,20 @@ public class ImgUtil {
 	}
 
 	/**
+	 * 将图片对象转换为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形式
 	 *
 	 * @param image     图片对象

+ 67 - 5
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)统一资源定位符相关工具类
+ *
+ * <p>
+ * 统一资源定位符,描述了一台特定服务器上某资源的特定位置。
+ * </p>
+ * URL组成:
+ * <pre>
+ *   协议://主机名[:端口]/ 路径/[:参数] [?查询]#Fragment
+ *   protocol :// hostname[:port] / path / [:parameters][?query]#fragment
+ * </pre>
  *
  * @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)的方式在网页中包含数据,<br>
+	 * 目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。常用于将图片嵌入网页。
+	 *
+	 * <p>
+	 * Data URI的格式规范:
+	 * <pre>
+	 *     data:[<mime type>][;charset=<charset>][;<encoding>],<encoded data>
+	 * </pre>
+	 *
+	 * @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)的方式在网页中包含数据,<br>
+	 * 目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。常用于将图片嵌入网页。
+	 *
+	 * <p>
+	 * Data URI的格式规范:
+	 * <pre>
+	 *     data:[<mime type>][;charset=<charset>][;<encoding>],<encoded data>
+	 * </pre>
+	 *
+	 * @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();
+	}
 }

+ 79 - 79
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 形式表示
 	 *
+	 * <p>
+	 *     输出格式为: data:image/[type];base64,[data]
+	 * </p>
+	 *
 	 * @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 {
 	/**
 	 * 生成二维码或条形码图片<br>
 	 * 只有二维码时QrConfig中的图片才有效
-	 * 
+	 *
 	 * @param content 文本内容
-	 * @param format 格式,可选二维码、条形码等
-	 * @param config 二维码配置,包括长、宽、边距、颜色等
+	 * @param format  格式,可选二维码、条形码等
+	 * @param config  二维码配置,包括长、宽、边距、颜色等
 	 * @return 二维码图片(黑白)
 	 * @since 4.1.14
 	 */
@@ -256,12 +254,13 @@ public class QrCodeUtil {
 	}
 
 	// ------------------------------------------------------------------------------------------------------------------- encode
+
 	/**
 	 * 将文本内容编码为二维码
-	 * 
+	 *
 	 * @param content 文本内容
-	 * @param width 宽度
-	 * @param height 高度
+	 * @param width   宽度
+	 * @param height  高度
 	 * @return {@link BitMatrix}
 	 */
 	public static BitMatrix encode(String content, int width, int height) {
@@ -270,9 +269,9 @@ public class QrCodeUtil {
 
 	/**
 	 * 将文本内容编码为二维码
-	 * 
+	 *
 	 * @param content 文本内容
-	 * @param config 二维码配置,包括长、宽、边距、颜色等
+	 * @param config  二维码配置,包括长、宽、边距、颜色等
 	 * @return {@link BitMatrix}
 	 * @since 4.1.2
 	 */
@@ -282,11 +281,11 @@ public class QrCodeUtil {
 
 	/**
 	 * 将文本内容编码为条形码或二维码
-	 * 
+	 *
 	 * @param content 文本内容
-	 * @param format 格式枚举
-	 * @param width 宽度
-	 * @param height 高度
+	 * @param format  格式枚举
+	 * @param width   宽度
+	 * @param height  高度
 	 * @return {@link BitMatrix}
 	 */
 	public static BitMatrix encode(String content, BarcodeFormat format, int width, int height) {
@@ -295,10 +294,10 @@ public class QrCodeUtil {
 
 	/**
 	 * 将文本内容编码为条形码或二维码
-	 * 
+	 *
 	 * @param content 文本内容
-	 * @param format 格式枚举
-	 * @param config 二维码配置,包括长、宽、边距、颜色等
+	 * @param format  格式枚举
+	 * @param config  二维码配置,包括长、宽、边距、颜色等
 	 * @return {@link BitMatrix}
 	 * @since 4.1.2
 	 */
@@ -319,9 +318,10 @@ public class QrCodeUtil {
 	}
 
 	// ------------------------------------------------------------------------------------------------------------------- decode
+
 	/**
 	 * 解码二维码图片为文本
-	 * 
+	 *
 	 * @param qrCodeInputstream 二维码输入流
 	 * @return 解码文本
 	 */
@@ -331,7 +331,7 @@ public class QrCodeUtil {
 
 	/**
 	 * 解码二维码图片为文本
-	 * 
+	 *
 	 * @param qrCodeFile 二维码文件
 	 * @return 解码文本
 	 */
@@ -341,7 +341,7 @@ public class QrCodeUtil {
 
 	/**
 	 * 将二维码图片解码为文本
-	 * 
+	 *
 	 * @param image {@link Image} 二维码图片
 	 * @return 解码后的文本
 	 */
@@ -351,9 +351,9 @@ public class QrCodeUtil {
 
 	/**
 	 * 将二维码图片解码为文本
-	 * 
-	 * @param image {@link Image} 二维码图片
-	 * @param isTryHarder 是否优化精度
+	 *
+	 * @param image         {@link Image} 二维码图片
+	 * @param isTryHarder   是否优化精度
 	 * @param isPureBarcode 是否使用复杂模式,扫描带logo的二维码设为true
 	 * @return 解码后的文本
 	 * @since 4.3.1
@@ -389,8 +389,8 @@ public class QrCodeUtil {
 
 	/**
 	 * BitMatrix转BufferedImage
-	 * 
-	 * @param matrix BitMatrix
+	 *
+	 * @param matrix    BitMatrix
 	 * @param foreColor 前景色
 	 * @param backColor 背景色(null表示透明背景)
 	 * @return BufferedImage
@@ -402,9 +402,9 @@ public class QrCodeUtil {
 		BufferedImage image = new BufferedImage(width, height, null == backColor ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
 		for (int x = 0; x < width; x++) {
 			for (int y = 0; y < height; y++) {
-				if(matrix.get(x, y)) {
+				if (matrix.get(x, y)) {
 					image.setRGB(x, y, foreColor);
-				} else if(null != backColor){
+				} else if (null != backColor) {
 					image.setRGB(x, y, backColor);
 				}
 			}

+ 6 - 8
hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java

@@ -1,16 +1,14 @@
 package cn.hutool.extra.qrcode;
 
-import java.awt.Color;
-import java.io.File;
-
 import cn.hutool.core.codec.Base64;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.lang.Console;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.lang.Console;
+import java.awt.Color;
+import java.io.File;
 
 /**
  * 二维码工具类单元测试
@@ -61,7 +59,7 @@ public class QrCodeUtilTest {
 		System.out.println(base64);
 
 		byte[] bytes = FileUtil.readBytes(
-			new File("e:/pic/qr.png"));
+			new File("d:/test/qr.png"));
 		String encode = Base64.encode(bytes);
 		String base641 = QrCodeUtil.generateAsBase64("http://hutool.cn/", new QrConfig(400, 400), "png", encode);
 		System.out.println(base641);