目的
因为业务需求,需要做一个生成二维码,并且导出为表格,在此举例,具体根据自己需求举一反三或者给予灵感。这个是通过谷歌的一个生成二维码的jar包,生成二维码,简单易懂,导入依赖即可用。不过下文是基于自己的理解,如果有不对的地方指出一下。
代码
第一步: 导入依赖
<!--二维码--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <scope>provided</scope> </dependency> <!--这个是解析二维码的依赖--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.0</version> </dependency>
第二步: 创建工具类
package com.hanlong.guns.core.util; import java.awt.*; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.OutputStream; import java.util.Hashtable; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatWriter; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; public class QRCodeUtil { private static final String CHARSET = "utf-8"; private static final String FORMAT_NAME = "JPG"; // 二维码尺寸 private static final int QRCODE_WIDTH = 300; private static final int QRCODE_HEIGHT = 300; private static final int QRCODE_SIZE = 300; // LOGO宽度 private static final int WIDTH = 60; // LOGO高度 private static final int HEIGHT = 60; private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception { Hashtable hints = new Hashtable(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//二维码的纠错程度 hints.put(EncodeHintType.CHARACTER_SET, CHARSET);//指定适用的字符编码 hints.put(EncodeHintType.MARGIN, 3);//二维码的白边,如果要展示二维码内容,建议留着 //生成二维码 BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_WIDTH, QRCODE_HEIGHT,hints); int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); //生成二维码的辅助类 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //按照指定大小将二维码生成在图像image中 for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } //不嵌入图像直接返回 if (imgPath == null || "".equals(imgPath)) { return image; } // 插入图片 QRCodeUtil.insertImage(image, imgPath, needCompress); return image; } private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception { File file = new File(imgPath); if (!file.exists()) { System.err.println("" + imgPath + " 该文件不存在!"); return; } Image src = ImageIO.read(new File(imgPath)); int width = src.getWidth(null); int height = src.getHeight(null); // 按照指定的大小压缩压缩LOGO if (needCompress) { if (width > WIDTH) { width = WIDTH; } if (height > HEIGHT) { height = HEIGHT; } Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); //BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //Graphics g = tag.getGraphics(); //g.drawImage(image, 0, 0, null); // 绘制缩小后的图 //g.dispose(); src = image; } // 插入LOGO Graphics2D graph = source.createGraphics(); int x = (QRCODE_SIZE - width) / 2; int y = (QRCODE_SIZE - height) / 2; graph.drawImage(src, x, y, width, height, null); Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); graph.setStroke(new BasicStroke(3f)); graph.draw(shape); graph.dispose(); } //二维码编码处理 public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); //若目标存储位置不存在,则新建生成位置 mkdirs(destPath); ImageIO.write(image, FORMAT_NAME, new File(destPath)); } //不传递存储路径调用 public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); return image; } //创建文件夹 public static void mkdirs(String destPath) { File file = new File(destPath); // 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常) if (!file.exists() && !file.isDirectory()) { file.mkdirs(); } } //不对嵌入图片进行压缩 public static void encode(String content, String imgPath, String destPath) throws Exception { QRCodeUtil.encode(content, imgPath, destPath, false); } //不嵌入图片 public static void encode(String content, String destPath) throws Exception { QRCodeUtil.encode(content, null, destPath, false); } public static void encode(String content, String imgPath, OutputStream output, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); ImageIO.write(image, FORMAT_NAME, output); } public static void encode(String content, OutputStream output) throws Exception { QRCodeUtil.encode(content, null, output, false); } //对文件进行解码操作 public static String decode(File file) throws Exception { BufferedImage image; image = ImageIO.read(file); if (image == null) { return null; } //解析二维码的辅助类 BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result; Hashtable hints = new Hashtable(); hints.put(DecodeHintType.CHARACTER_SET, CHARSET); result = new MultiFormatReader().decode(bitmap, hints); String resultStr = result.getText(); return resultStr; } public static String decode(String path) throws Exception { return QRCodeUtil.decode(new File(path)); } /** * 给二维码下方附加说明文字 * * @param pressText 文字 * @param newImg 带文字的图片 * @param image 需要添加文字的图片 * @为图片添加文字 */ public static BufferedImage pressText(String pressText, String newImg, BufferedImage image, int fontStyle, Color color, int fontSize, int width, int height) { /** * 这个地方代表二维码图片上哪个地方需要写上文字,如果没有设置好就会重叠在一起 * 在生成二维码的时候适当留点白边展示文字 */ //计算文字开始的位置 //x开始的位置:(图片宽度-字体大小*字的个数)/2 int startX = 95; //这个地方好像有固定算法,不过我管他花里胡哨,直接按照需求设置 // int startX = (width - (fontSize * pressText.length())) / 3 - 28; //y开始的位置:图片高度-(图片高度-图片宽度)/2 int startY = 290; // int startY = height - (height - width) / 2 - 30; try { int imageW = image.getWidth(); int imageH = image.getHeight(); Graphics g = image.createGraphics(); g.drawImage(image, 0, 0, imageW, imageH, null); g.setColor(color); g.setFont(new Font("粗体", Font.BOLD, 18)); g.drawString(pressText, startX, startY); g.drawString("", startX - 5, startY + 30); g.dispose(); //这个地方是插入二维码中间图标的 // FileOutputStream out = new FileOutputStream(newImg); // ImageIO.write(image, "png", out); // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); // encoder.encode(image); // out.close(); //System.out.println("image press success"); return image; } catch (Exception e) { e.printStackTrace(); System.out.println(e); } return null; } }
第三步: 使用工具
在这里面有的包是会报红的,根据自己的需求去做,我会保留核心代码。
public class TbconsoleCardController { /** * 导出 */ @RequestMapping(value = "/exportExcel") @ResponseBody public void exportExcel(HttpServletResponse response) { List<BufferedImage> imgList = createQrCode("批量的二维码内容"); //导出表格 exceImgList(imgList, response); } /** * 批量生成二维码 */ public List<BufferedImage> createQrCode(List<String> deccaNoList){ List<BufferedImage> imgList = new ArrayList<>(); int width = 300; int height = 380; int font = 10; //字体大小 int fontStyle = 1; //字体风格 for (String "二维码内容": deccaNoList) { try { BufferedImage encode = QRCodeUtil.encode("二维码内容", null, true); BufferedImage image = QRCodeUtil.pressText("二维码内容", "", encode, fontStyle, Color.black, font, width, height); imgList.add(image); } catch (Exception e) { throw new RuntimeException(e); } } return imgList; } /** * 导出批量生成的二维码 * @param imgList * @param response */ public void exceImgList(List<BufferedImage> imgList,HttpServletResponse response){ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet1 = wb.createSheet("二维码"); sheet1.setColumnWidth(0, 45*256); sheet1.setDefaultRowHeight((short)(4636)); //画图的顶级管理器,一个sheet只能获取一个(一定要注意这点) HSSFPatriarch patriarch = sheet1.createDrawingPatriarch(); FileOutputStream fileOut = null; try { int i = 0; for (BufferedImage encode : imgList) { // 先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); ImageIO.write(encode, "png", byteArrayOut); // anchor主要用于设置图片的属性 /** * 该构造函数有8个参数 * 前四个参数是控制图片在单元格的位置,分别是图片距离单元格left,top,right,bottom的像素距离 * 后四个参数,前两个表示图片左上角所在的cellNum和 rowNum,后两个参数对应的表示图片右下角所在的cellNum和 rowNum, * excel中的cellNum和rowNum的index都是从0开始的 */ HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1020, 255,(short) 0, i, (short) 0, i); // 插入图片 patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); i++; } } catch (Exception e) { throw new RuntimeException(e); }finally { if (fileOut != null) { try { fileOut.close(); } catch (IOException e) { e.printStackTrace(); } } } //这个地方可选导出到表格,也可导出到指定的文件夹 try { response.setContentType("application/vnd.ms-excel;"); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("二维码", "UTF-8")+".xls"); wb.write(response.getOutputStream()); } catch (IOException e) { throw new RuntimeException(e); } } }
结果:
其他文献
java生成二维码图片(有logo),并在图片下方附文字_新丨客的博客-CSDN博客
【Java】------- Java实现多个二维码图片生成并存入Excel文件中然后下载(可以添加图标,和文字)_java 批量下载二维码返回excel_皮皮冰要做大神的博客-CSDN博客