需求
在一些教学系统中,经常会用到一些证书自定义生成,提供一个模板,写入不同姓名、获得的奖项、描述等,本篇文章就是处理这类需求的。
代码
1、引入依赖
<!-- cmyk格式图片转换 --> <dependency> <groupId>org.sejda.imageio</groupId> <artifactId>webp-imageio</artifactId> <version>0.1.6</version> </dependency>
2、实体类
@Data public class CertificateParam { private Long id; /** * 证书图片 */ private String certificateImg; /** * 证书导入参数 */ private List<CertificateConfigParam> certificateConfigParams; }
@Data public class CertificateConfigParam { /** * 要绘制的内容 **/ private String context; /** * 位置:横坐标 **/ private Integer x; /** * 位置:纵坐标 **/ private Integer y; /** * 字体大小 **/ private Integer fontSize; /** * 字体 **/ private String font; /** * 字体颜色(RGB Color对象) **/ private String color; }
3、Controller
@PostMapping("/getCertificatePreviewPicture") public String getCertificatePreviewPicture(@RequestBody CertificateParam certificateParam,HttpServletResponse response) { response.addHeader("request-type", "download"); response.addHeader("Access-Control-Expose-Headers", "request-type"); return bizCertificateService.getCertificatePreviewPicture(certificateParam); }
4、Service
String getCertificatePreviewPicture(CertificateParam certificateParam);
5、ServiceImpl
@Override public String getCertificatePreviewPicture(CertificateParam certificateParam) { return Base64.getEncoder().encodeToString(CertificatePictureUtil.getCertificatePictureByte(certificateParam)); }
6、Utils
public class CertificatePictureUtil { /** * @Description 根据传入的证书参数和证书模板参数去生成证书字节数据 * @Date 15:52 2023/4/25 * @Param [certificateParam, response] * @Return byte[] **/ public static byte[] getCertificatePictureByte(CertificateParam certificateParam){ try { //获取底图 URL url = new URL(certificateParam.getCertificateImg()); URLConnection resource = url.openConnection(); InputStream inputStream = resource.getInputStream(); //文件转化为图片 Image srcImg = ImageIO.read(inputStream); //获取图片的宽、高 int srcImgWidth = srcImg.getWidth(null); int srcImgHeight = srcImg.getHeight(null); // 设置画布大小 BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = bufImg.createGraphics(); g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null); // 证书中写字 List<CertificateConfigParam> certificateConfigParams = certificateParam.getCertificateConfigParams(); if(ObjectUtil.isNotEmpty(certificateConfigParams)){ for (CertificateConfigParam certificateConfigParam : certificateConfigParams) { setMark(g, certificateConfigParam.getContext(), srcImgWidth, srcImgHeight, certificateConfigParam.getX(), certificateConfigParam.getY(),certificateConfigParam.getFontSize(), certificateConfigParam.getFont(), certificateConfigParam.getColor()); } } else { throw new RuntimeException("证书参数错误"); } //画出内容 g.dispose(); // 下载证书 ByteArrayOutputStream bs = new ByteArrayOutputStream(); ImageOutputStream imOut = ImageIO.createImageOutputStream(bs); ImageIO.write(bufImg, "png", imOut); //关闭流 bs.close(); inputStream.close(); imOut.close(); return bs.toByteArray(); } catch (IOException e) { throw new RuntimeException("证书生成失败"); } } /** * 设置水印 * * @param graphics2D 绘图对象 * @param context 要绘制的内容 * @param srcImgWidth 原图的宽度 * @param srcImgHeight 原图的高度 * @param x 位置:横坐标 * @param y 位置:纵坐标 * @param font 字体 * @param fontSize 字体大小 * @param color 字体颜色(RGB Color对象) */ private static void setMark(Graphics2D graphics2D, String context, Integer srcImgWidth, Integer srcImgHeight, Integer x, Integer y,Integer fontSize, String font, String color) { // 获取图片相对500 * 708 的相对坐标,以及字体大小 fontSize=(int) ((srcImgWidth / 500.00) * fontSize); x = (int) ((srcImgWidth / 500.00) * x); y = (int) ((srcImgHeight / 708.00) * y)+fontSize; // 设置字体 graphics2D.setFont(new Font(font, Font.PLAIN, fontSize)); // 设置颜色 try { graphics2D.setColor(Color.decode(color)); } catch (Exception e) { throw new RuntimeException("不存在该种颜色,请重新设置"); } // 获取文本宽度 int textWidth = graphics2D.getFontMetrics().stringWidth(context); // 写字 graphics2D.drawString(new String(context.getBytes(StandardCharsets.UTF_8)), x - textWidth, y); } }
注意事项:
代码在本地跑时,写入中文内容正常,但是部署到Linux环境出现乱码,解决办法:需要在Linux安装字体库(具体教程网上很多),安装好字体库后一定记得记得重启项目。