第一步:导依赖包(使用的是Qrcode的方法)
<!--生成二维码,这个jar包可能不容易下载,需要手动将jar包放入maven仓库里--> <dependency> <groupId>Qrcode_swetake</groupId> <artifactId>Qrcode_swetake</artifactId> <version>1.0</version> </dependency> <!--base64流,应用将二维码转为base64流--> <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis</artifactId> <version>1.4</version> </dependency>第二步:工具类
public class QRCodeUtil { // 生成二维码 content:二维码里面的内容 qrcodeVersion:决定着大小 public static BufferedImage encoderQRCoder(String content, int qrcodeVersion) { try { Qrcode handler = new Qrcode(); /*表示的字符串长度: 容错率(ECC) 显示编码模式(EncodeMode)及版本(Version)有关*/ /*二维码的纠错级别(排错率),共有四级:可选L(7%)、M(15%)、Q(25%)、H(30%)(最高H)。 纠错信息同样存储在二维码中,纠错级别越高,纠错信息占用的空间越多,那么能存储的有用信息就越少,对二维码清晰度的要求越小 */ handler.setQrcodeErrorCorrect('M'); //编码模式:Numeric 数字, Alphanumeric 英文字母,Binary 二进制,Kanji 汉字(第一个大写字母表示) handler.setQrcodeEncodeMode('B'); handler.setQrcodeVersion(qrcodeVersion); byte[] contentBytes = content.getBytes("UTF-8"); // 67 + 12 * (v - 1); int size = 67 + 12 * (qrcodeVersion -1); BufferedImage bufImg = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); Graphics2D gs = bufImg.createGraphics(); gs.setBackground(Color.WHITE); gs.clearRect(0, 0, size, size); //设定图像颜色:BLACK gs.setColor(Color.BLACK); //设置偏移量 不设置肯能导致解析出错 int pixoff = 2; //输出内容:二维码 if(contentBytes.length > 0 && contentBytes.length < 1024) { boolean[][] codeOut = handler.calQrcode(contentBytes); for(int i = 0; i < codeOut.length; i++) { for(int j = 0; j < codeOut.length; j++) { if(codeOut[j][i]) { gs.fillRect(j * 3 + pixoff, i * 3 + pixoff,3, 3); } } } } else { System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,120 ]. "); } gs.dispose(); bufImg.flush(); //生成二维码QRCode图片 return bufImg; } catch (Exception e) { e.printStackTrace(); } return null; } }第三步,应用,根据我的业务来,是需要在添加机具的方法里,调用生成二维码的方法,
//添加后 this.save(machine); //移动端扫描需要的格式是这样的,所以就将这样的格式作为content放进二维码里 //{"type":1,“params”:{"machineId":111,"projcetId":222,"bidSectionId":333}} Map<String,Object> map=new HashMap<>(); map.put("machineId", machine.getMachineId());//新添加的机具id map.put("projectId",machine.getProjectId());//新添加的机具所在项目 map.put("bidSectionId",machine.getBidSectionId());//新添加的机具所在标段 // JSONObject machineJson=new JSONObject(); machineJson.put("type",1); //考虑到后面有很多模块需要做二维码功能,所以拿type做区分,机具就是type为1 machineJson.put("params",map); String machineString = machineJson.toJSONString(); // 生成二维码图片 BufferedImage bufferedImage = QRCodeUtil.encoderQRCoder(machineString,20); String base64 = null; try { //输出流 ByteArrayOutputStream stream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "png", stream); base64 = Base64.encode(stream.toByteArray()); //机具表里存的有二维码字段,因为在添加前没有机具id,所以在save方法执行后拿到机具id再进行修改操作, //此时只修二维码,之前为空字符串,所以此时的修改相当于添加了。之后将这个字段返回给前端,剩下的就是前端拿这个流去进行解析了 Machine m=new Machine(); m.setQrCode(String.format("%1$s%2$s","data:image/png;base64,",base64)); m.setMachineId(machine.getMachineId()); this.updateById(m); } catch (Exception e) { e.printStackTrace(); } return true;业务更改,不是添加的时候生成二维码,而是在查询的时候,前端传我一个机具id,点击查看二维码的时候调这个接口,将二维码和一些基本信息返回给他。
@ResponseBody @RequestMapping(value = {"/createQrCode"}, method = RequestMethod.GET) public JSONObject createQrCode(@RequestParam(value = "machineId")String machineId){ Machine machine = machineService.getById(machineId); String format=""; if (machine.getEnterDate()!=null){ Timestamp enterDate = machine.getEnterDate(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); format = dateFormat.format(enterDate); }else{ format ="/"; } // 返回的信息 JSONObject jsonObject=new JSONObject(); jsonObject.put("machineName",machine.getMachineName()); jsonObject.put("machineNo",machine.getMachineNo()); jsonObject.put("specificationType",machine.getSpecificationType()); jsonObject.put("enterDate",format); //二维码的内容 JSONObject qrCodeJson=new JSONObject(); qrCodeJson.put("type",1); qrCodeJson.put("mId",machine.getMachineId()); qrCodeJson.put("pId",machine.getProjectId()); qrCodeJson.put("bId",machine.getBidSectionId()); String qrCodeString = qrCodeJson.toJSONString(); //二维码流 String base64Image = createImage(qrCodeString); jsonObject.put("qrCode",String.format("%1$s%2$s","data:image/png;base64,",base64Image)); return ReturnUtil.success(jsonObject); } // 创建二维码并生成流 public static String createImage(String content) { // 生成二维码图片 BufferedImage bufferedImage = QRCodeUtil.encoderQRCoder(content,5); String base64 = null; try { //输出流 ByteArrayOutputStream stream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "png", stream); base64 = Base64.encode(stream.toByteArray()); } catch (Exception e) { e.printStackTrace(); } return base64; }ps :bufferedImage和base64的互转 https://www.2loveyou.com/articles/2020/01/19/1579401149903.html
所需工具类:
/** * 生成压缩文件 (zip,rar 格式) */ public class CompressUtil { /** * 多文件zip压缩下载 (说明:读取文件流到zip流中,之后下载) * @param response * @param downloadName 下载后的压缩包名,带后缀 * @param map 存放文件信息的map ,key为该文件压缩后的目录层级路径如:/xxx/xxx/xxx.jpg,为文件名时则在压缩包的顶层 * 如:xxx.jpg。 value为下载文件所在的路径 */ public static void MultiFileZipDownload(HttpServletResponse response, String downloadName, Map<String,String> map) { OutputStream outputStream = null; try { outputStream = response.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } ZipOutputStream zos=new ZipOutputStream(outputStream); try { response.setContentType("multipart/form-data"); response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadName, "UTF-8")); map.forEach((name,path)->{ InputStream is = null; BufferedInputStream in = null; byte[] buffer = new byte[1024]; int len; //创建zip实体(一个文件对应一个ZipEntry) //name --->压缩包的层级路径 ZipEntry entry = new ZipEntry(name); try { //获取需要下载的文件流 File file=new File(path); is = new FileInputStream(file); in = new BufferedInputStream(is); zos.putNextEntry(entry); //文件流循环写入ZipOutputStream while ((len = in.read(buffer)) != -1 ) { zos.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); }finally { if(entry != null) { try { zos.closeEntry(); } catch (Exception e) { e.printStackTrace(); } } if(in != null) { try { in.close(); } catch (Exception e) { e.printStackTrace(); } } if(is != null) { try { is.close(); }catch (Exception e) { e.printStackTrace(); } } } }); } catch (IOException e) { e.printStackTrace(); }finally { if(zos != null) { try { zos.close(); } catch (Exception e2) { e2.printStackTrace(); } } if(outputStream != null) { try { outputStream.close(); } catch (Exception e2) { e2.printStackTrace(); } } } } /** * @param path 要压缩的文件路径 * @param format 生成的格式(zip、rar)d */ public static void generateFile(String path, String format) throws Exception { File file = new File(path); // 压缩文件的路径不存在 if (!file.exists()) { throw new Exception("路径 " + path + " 不存在文件,无法进行压缩..."); } // 用于存放压缩文件的文件夹 String generateFile = file.getParent(); File compress = new File(generateFile); // 如果文件夹不存在,进行创建 if( !compress.exists() ){ compress.mkdirs(); } // 目的压缩文件 String generateFileName = compress.getAbsolutePath() + File.separator + file.getName() + "." + format; // 输入流 表示从一个源读取数据 // 输出流 表示向一个目标写入数据 // 输出流 FileOutputStream outputStream = new FileOutputStream(generateFileName); // 压缩输出流 ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(outputStream)); generateFile(zipOutputStream,file,""); System.out.println("源文件位置:" + file.getAbsolutePath() + ",目的压缩文件生成位置:" + generateFileName); // 关闭 输出流 zipOutputStream.close(); } /** * @param out 输出流 * @param file 目标文件 * @param dir 文件夹 * @throws Exception */ private static void generateFile(ZipOutputStream out, File file, String dir) throws Exception { // 当前的是文件夹,则进行一步处理 if (file.isDirectory()) { //得到文件列表信息 File[] files = file.listFiles(); //将文件夹添加到下一级打包目录 out.putNextEntry(new ZipEntry(dir + "/")); dir = dir.length() == 0 ? "" : dir + "/"; //循环将文件夹中的文件打包 for (int i = 0; i < files.length; i++) { generateFile(out, files[i], dir + files[i].getName()); } } else { // 当前是文件 // 输入流 FileInputStream inputStream = new FileInputStream(file); // 标记要打包的条目 out.putNextEntry(new ZipEntry(dir)); // 进行写操作 int len = 0; byte[] bytes = new byte[1024]; while ((len = inputStream.read(bytes)) > 0) { out.write(bytes, 0, len); } // 关闭输入流 inputStream.close(); } } /** * 迭代删除文件夹 * @param dirPath 文件夹路径 */ public static void deleteDir(String dirPath) { File file = new File(dirPath); if(file.isFile()) { file.delete(); }else { File[] files = file.listFiles(); if(files == null) { file.delete(); }else { for (int i = 0; i < files.length; i++) { deleteDir(files[i].getAbsolutePath()); } file.delete(); } } } }