1. 生成微信图片我所想的有两种方式
2. 想到的两种方法各有好处
3. 准备工作
4.14
2.3.28
net.sf.cssbox
cssbox
${version.cssbox}
org.springframework.boot
spring-boot-starter-freemarker
${version.freemarker}
freemarker:
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html #生成模板类型选择html
enabled: true
suffix: .ftl #设置默认读取模板文件的后缀
template-loader-path: classpath:/templates #模板文件所在的地址
public interface ITemplateService {
//我返回的输入流在后面好输入到cssbox
InputStream getHtmlInputStream(Map root, String template) throws Exception;
}
@Service
public class TemplateServiceImpl implements ITemplateService {
@Resource
Configuration cfg;
/**
* 获取生成模板inputStream
* @param root
* @param template
* @return
* @throws Exception
*/
public InputStream getHtmlInputStream(Map root,String template) throws Exception {
Template temp = cfg.getTemplate(template+".ftl");
StringWriter out = new StringWriter();
temp.process(root, out);
StringBuffer buffer = out.getBuffer();
return new ByteArrayInputStream(new String(buffer).getBytes());
}
}
创建模板文件我的模板文件比较多就不粘出来了
//map 里存的模板里面可以用的变量
HashMap map = new HashMap<>();
//背景图
map.put("background", shareService.getRandomPic().getPicUrl());
InputStream htmlStream = templateService.getHtmlInputStream(map, "activity_details_singer");
得到的输入流到时候可以用于cssbox
复写 DocumentSource 文档源添加输入源方式输入流输入
public class StreamAndUrlDocumentSource extends DocumentSource {
private InputStream inputStream;
private static String USER_AGENT = "Mozilla/5.0 (compatible; BoxBrowserTest/4.x; Linux) CSSBox/4.x (like Gecko)";
private URLConnection con;
public StreamAndUrlDocumentSource(URL base, String urlstring) throws IOException {
super(base, urlstring);
URL url = DataURLHandler.createURL(base, urlstring);
this.con = this.createConnection(url);
this.inputStream = null;
}
public StreamAndUrlDocumentSource(URL url) throws IOException {
super(url);
this.con = this.createConnection(url);
this.inputStream = null;
}
public StreamAndUrlDocumentSource(String urlstring) throws IOException {
super((URL)null, urlstring);
URL url = DataURLHandler.createURL((URL)null, urlstring);
this.con = this.createConnection(url);
this.inputStream = null;
}
public StreamAndUrlDocumentSource(InputStream inputStream) throws IOException {
super(null);
this.inputStream =inputStream;
}
@Override
public URL getURL() {
URL url =null;
if(this.con != null)
url = this.con.getURL();
return url;
}
@Override
public String getContentType() {
String s =null;
if(this.con != null)
s = this.con.getHeaderField("Content-Type");
return s;
}
@Override
public InputStream getInputStream() throws IOException {
if (this.inputStream == null) {
this.inputStream = this.con.getInputStream();
}
return this.inputStream;
}
@Override
public void close() throws IOException {
if (this.inputStream != null) {
this.inputStream.close();
}
}
protected URLConnection createConnection(URL url) throws IOException {
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", USER_AGENT);
return con;
}
}
cssbox 的service
public interface IShareService {
void htmlToPicture(DocumentSource docSource, OutputStream out, Dimension windowSize) throws IOException, SAXException;
}
public class ShareServiceImpl extends BaseService implements IShareService {
private String mediaType = "screen";
//方法的out是生成图片后的输出流
@Override
public void htmlToPicture(DocumentSource docSource, OutputStream out, Dimension windowSize) throws IOException, SAXException {
DOMSource parser = new DefaultDOMSource(docSource);
Document doc = parser.parse();
MediaSpec media = new MediaSpec(mediaType);
media.setDimensions((float)windowSize.width, (float)windowSize.height);
media.setDeviceDimensions((float)windowSize.width, (float)windowSize.height);
DOMAnalyzer da = new DOMAnalyzer(doc);
da.setMediaSpec(media);
da.attributesToStyles();
da.addStyleSheet((URL)null, CSSNorm.stdStyleSheet(), DOMAnalyzer.Origin.AGENT);
da.addStyleSheet((URL)null, CSSNorm.userStyleSheet(), DOMAnalyzer.Origin.AGENT);
da.addStyleSheet((URL)null, CSSNorm.formsStyleSheet(), DOMAnalyzer.Origin.AGENT);
da.getStyleSheets();
BrowserCanvas contentCanvas = new BrowserCanvas(da.getRoot(), da, docSource.getURL());
contentCanvas.setAutoMediaUpdate(false);
contentCanvas.getConfig().setClipViewport(false);
contentCanvas.getConfig().setLoadImages(true);
contentCanvas.getConfig().setLoadBackgroundImages(true);
contentCanvas.createLayout(windowSize);
//生成图片的类型可以是svg
ImageIO.write(contentCanvas.getImage(), "png", out);
docSource.close();
}
//接收的输出流
ByteArrayOutputStream out = new ByteArrayOutputStream();
//htmlStream 生成的html输入流
//streamAndUrlDocumentSource为 生成png的文件源
StreamAndUrlDocumentSource streamAndUrlDocumentSource = new StreamAndUrlDocumentSource(htmlStream);
shareService.htmlToPicture(streamAndUrlDocumentSource, out, new Dimension(width, height));
//关闭输入流
htmlStream.close();
ps:如果你想接口直接返回一直图片的可以将out设置为:
//response 为 HttpServletResponse
ServletOutputStream out = response.getOutputStream()
这样你请求接口就直接返回的是一张图片
关于这个out可以随便处理放入文件,上传oss,转base64都可以
最后的生成效果
二维码与上面的文字与背景图都是变化的