网上的html2image v1版本html2image转成图片后的css和style会有问题 v2.0.1修复了
导入以下依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>gui.ava</groupId> <artifactId>html2image</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>core-renderer</artifactId> <version>R8</version> </dependency>freemarker模板
freemarker模板放在/resources/template下面
template.ftl
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<style>
*{ margin:0px; padding:0px;}
</style>
</head>
<body>
<div style="width: 453px; height: 662px; margin: 0px auto; position: relative;">
<img src="图片地址" width="100%">
<img src=${imgQrCode} style="width: 103px; height: 103px; border-radius: 8px; position: absolute; right: 22px; bottom: 25px;">
</div>
</body>
</html>
ImageUtil 图片工具类
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import gui.ava.html.Html2Image;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Map;
public class ImageUtil {
/**
* 获取模板
* @param templateName 模板名,如test.ftl
* @return
*/
public static Template getTemplate(String templateName) throws IOException, TemplateException{
/*初始化freemarker模板*/
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding(Charset.forName("UTF-8").name());
configuration.setTemplateLoader(new ClassTemplateLoader(ImageUtil.class,"/template/"));
//获取模板
Template T = configuration.getTemplate(templateName);
return T;
}
/**
* HTML转图片
* @param data 填充数据
* @param template html模板
* @return
*/
public static byte[] htmlToImage(Map<String, String> data, Template template){
if (template == null){
throw new RuntimeException("The template is not found ...");
}
try {
StringWriter stringWriter = new StringWriter();
BufferedWriter bufferedWriter = new BufferedWriter(stringWriter);
template.process(data, bufferedWriter);
bufferedWriter.flush();
bufferedWriter.close();
// 旧版本css样式会有问题使用新版本
// HtmlImageGenerator imageGenerator = new HtmlImageGenerator();
// imageGenerator.loadHtml(stringWriter.toString());
// HtmlParser htmlParser = new HtmlParserImpl();
// htmlParser.loadHtml(stringWriter.toString()); // 载入html
Html2Image image1 = Html2Image.fromHtml(stringWriter.toString());
image1.getImageRenderer().setWidth(453);
image1.getImageRenderer().setHeight(662);
image1.getImageRenderer().setAutoHeight(false);
BufferedImage image = image1.getImageRenderer().getBufferedImage();
BufferedImage bufferedImageToWrite = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
bufferedImageToWrite.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
// ImageRenderer imageRenderer = new ImageRendererImpl(htmlParser);;
// imageRenderer.saveImage("E:\\lcyq.png");//保存图片到本地
// BufferedImage bufferedImage = imageRenderer.getBufferedImage();
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
ImageIO.write(bufferedImageToWrite, "png", os);
os.close();
return os.toByteArray();
} catch (TemplateException | IOException e) {
e.printStackTrace();
}
return null;
}
}
PoliteInvitationDTO
@Data
public class PoliteInvitationDTO {
@ApiModelProperty(value = "会员code")
private String memberCode;
@ApiModelProperty(value = "模板Id")
private Long templateId;
@ApiModelProperty(value = "如果初次生成邀请图则该字段为空")
private String politeInvitationPic;
}
impl里面实现
private static Template t; static { try { t = ImageUtil.getTemplate("template.ftl"); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } }@Override @Transactional(rollbackFor = Exception.class) public String politeInvitationOne(PoliteInvitationDTO politeInvitation) throws IOException { Map<String, String> data = new HashMap<>(); String QrCode = inviterService.inviterWxCode(inviter.getId(),politeInvitation.getTemplateId()); data.put("imgBg", invitationTemplate.getMediaBanner1()); data.put("imgQrCode", QrCode); byte[] picture = ImageUtil.htmlToImage(data, t); if (null == picture) { throw new ServiceException("图片转换有误"); } String fileName = inviter.getName() + "——" + inviter.getUserName(); Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("originalName", fileName + "." + FileTypeEnum.PNG.getDesc())); InputStream inputStream = new ByteArrayInputStream(picture); StorePath storePath = fastDao.uploadImageAndCrtThumbImage(inputStream, inputStream.available(), FileTypeEnum.PNG.getDesc(), metaDataSet); if (!ObjectUtils.isEmpty(storePath)) { // 存到media表 Media media = new Media(); // 存储源文件名 media.setMediaName(fileName + "." + FileTypeEnum.PNG.getDesc()); // 存储文件读写权限 media.setPermission(FilePermissionEnum.PUBLIC_READ_WRITE); // 存储业务类型 media.setBusinessType(FileBusinessTypeEnum.POLITE_INVITATION); // 存储文件类型 media.setMediaType(FileTypeEnum.PNG); // 存储文件唯一标识符 media.setKey(UuidUtils.createUuid()); //存储文件对应的外键Id media.setForeignId(inviter.getId()); // 存储文件路径 media.setUrl(fastDao.getUrlPrefix() + storePath.getFullPath()); // 创建人 media.setCreatorId(0L); mediaDao.insert(media); return fastDao.getUrlPrefix() + storePath.getFullPath(); }} else{ InvitationTemplate invitationTemplate = invitationTemplateDao.selectById(politeInvitation.getTemplateId()); Inviter inviter = inviterDao.selectByMemberCode(politeInvitation.getMemberCode()); data.put("imgBg", invitationTemplate.getMediaBanner1()); data.put("imgQrCode", inviter.getQrCode()); byte[] picture = ImageUtil.htmlToImage(data, t); if (null == picture) { throw new ServiceException("图片转换有误"); } String fileName = inviter.getName() + "——" + inviter.getUserName(); Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("originalName", fileName + "." + FileTypeEnum.PNG.getDesc())); InputStream inputStream = new ByteArrayInputStream(picture); StorePath storePath = fastDao.uploadImageAndCrtThumbImage(inputStream, inputStream.available(), FileTypeEnum.PNG.getDesc(), metaDataSet); if (!ObjectUtils.isEmpty(storePath)) { // 存到media表 Media media = new Media(); // 存储源文件名 media.setMediaName(fileName + "." + FileTypeEnum.PNG.getDesc()); // 存储文件读写权限 media.setPermission(FilePermissionEnum.PUBLIC_READ_WRITE); // 存储业务类型 media.setBusinessType(FileBusinessTypeEnum.POLITE_INVITATION); // 存储文件类型 media.setMediaType(FileTypeEnum.PNG); // 存储文件唯一标识符 media.setKey(UuidUtils.createUuid()); //存储文件对应的外键Id media.setForeignId(inviter.getId()); // 存储文件路径 media.setUrl(fastDao.getUrlPrefix() + storePath.getFullPath()); // 创建人 media.setCreatorId(0L); mediaDao.insert(media); return fastDao.getUrlPrefix() + storePath.getFullPath(); } } return StringUtils.EMPTY; }