1.WkTests 简单测试生成图片
import java.io.IOException;
public class WkTests {
public static void main(String[] args) {
String cmd="F:/wkhtmltopdf/bin/wkhtmltoimage --quality 75 https://www.nowcoder.com d:/work/data/wk-images/3.png";
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.配置 生成图片的命令 和 图片储存路径
#wk
wk:
image:
command: F:/wkhtmltopdf/bin/wkhtmltoimage
storage: d:/work/data/wk-images
3.在程序启动时,自动创建图片储存路径 WkConfig
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.File;
@Configuration
public class WkConfig {
private static Logger logger= LoggerFactory.getLogger(WkConfig.class);
@Value("${wk.image.storage}")
private String wkImageStorage;
@PostConstruct
public void init(){
//创建wk图片目录
File file = new File(wkImageStorage);
if (!file.exists()){
file.mkdir();
logger.info("创建wk图片目录:"+wkImageStorage);
}
}
}
4.ShareController
import com.nowcoder.community.entity.Event;
import com.nowcoder.community.event.EventProducer;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Controller
public class ShareController implements CommunityConstant {
private static final Logger logger= LoggerFactory.getLogger(ShareController.class);
@Autowired
private EventProducer eventProducer;
@Value("${community.path.domain}")
private String domain;
@Value("${server.servlet.context-path}")
private String contextPath;
@Value("${wk.image.storage}")
private String wkImageStorage;
@GetMapping("/share")
@ResponseBody
public String share(String htmlUrl){
//文件名
String fileName = CommunityUtil.generateUUID();
//异步生成长图
Event event = new Event()
.setTopic(TOPIC_SHARE)
.setData("htmlUrl",htmlUrl)
.setData("fileName",fileName)
.setData("suffix",".png");
eventProducer.fireEvent(event);
//返回访问路径
Map<String,Object> map=new HashMap<>();
map.put("shareUrl",domain+contextPath+"/share/image/"+fileName);
return CommunityUtil.getJSONString(0,null,map);
}
//获取长图
@GetMapping("/share/image/{fileName}")
public void getShareImage(@PathVariable("fileName") String fileName, HttpServletResponse response){
if (StringUtils.isBlank(fileName)){
throw new IllegalArgumentException("文件名不能为空!");
}
response.setContentType("image/png");
File file=new File(wkImageStorage+"/"+fileName+".png");
try {
ServletOutputStream os = response.getOutputStream();
FileInputStream fis=new FileInputStream(file);
byte[] buffer=new byte[1024];
int len=0;
while ((len= fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
} catch (IOException e) {
logger.error("获取长图失败:"+e.getMessage());
}
}
}
5.创建消费分享事件 EventConsumer
import com.alibaba.fastjson.JSONObject;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Event;
import com.nowcoder.community.entity.Message;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.service.ElasticsearchService;
import com.nowcoder.community.service.MessageServiceImpl;
import com.nowcoder.community.util.CommunityConstant;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class EventConsumer implements CommunityConstant {
private static final Logger logger= LoggerFactory.getLogger(EventConsumer.class);
@Autowired
private MessageServiceImpl messageService;
@Autowired
private DiscussPostServiceImpl discussPostService;
@Autowired
private ElasticsearchService elasticsearchService;
@Value("${wk.image.command}")
private String wkImageCommand;
@Value("${wk.image.storage}")
private String wkImageStorage;
@KafkaListener(topics = {TOPIC_COMMENT,TOPIC_FOLLOW,TOPIC_LIKE})
public void handleCommentMessage(ConsumerRecord record){
if (record==null||record.value()==null){
logger.error("消息的内容为空!");
return;
}
Event event= JSONObject.parseObject(record.value().toString(),Event.class);
if (event==null){
logger.error("消息格式错误!");
return;
}
//发送站内通知
Message message=new Message();
message.setFromId(SYSTEM_USER_ID);
message.setToId(event.getEntityUserId());
message.setConversationId(event.getTopic());
message.setCreateTime(new Date());
Map<String,Object> content=new HashMap<>();
content.put("userId",event.getUserId());
content.put("entityType",event.getEntityType());
content.put("entityId",event.getEntityId());
if (!event.getData().isEmpty()){
for (Map.Entry<String, Object> entry : event.getData().entrySet()) {
content.put(entry.getKey(), entry.getValue());
}
}
message.setContent(JSONObject.toJSONString(content));
messageService.addMessage(message);
}
//消费发帖事件
@KafkaListener(topics = {TOPIC_PUBLISH})
public void handlePublishMessage(ConsumerRecord record){
if (record==null||record.value()==null){
logger.error("消息的内容为空!");
return;
}
Event event=JSONObject.parseObject(record.value().toString(),Event.class);
if (event==null){
logger.error("消息格式错误!");
return;
}
DiscussPost post = discussPostService.selectDiscussPostById(event.getEntityId());
elasticsearchService.saveDiscussPost(post);
}
//消费删帖事件
@KafkaListener(topics = {TOPIC_DELETE})
public void handleDeleteMessage(ConsumerRecord record){
if (record==null||record.value()==null){
logger.error("消息的内容为空!");
return;
}
Event event = JSONObject.parseObject(record.value().toString(), Event.class);
if (event==null){
logger.error("消息格式错误!");
return;
}
elasticsearchService.deleteDiscussPost(event.getEntityId());
}
//消费分享事件
@KafkaListener(topics = {TOPIC_SHARE})
public void handleShareMessage(ConsumerRecord record){
if (record==null||record.value()==null){
logger.error("消息格式错误!");
return;
}
Event event=JSONObject.parseObject(record.value().toString(),Event.class);
if (event==null){
logger.error("消息格式错误!");
return;
}
String htmlUrl = (String) event.getData().get("htmlUrl");
String fileName = (String) event.getData().get("fileName");
String suffix = (String) event.getData().get("suffix");
String cmd=wkImageCommand+" --quality 75 "+htmlUrl+" "+wkImageStorage+"/"+fileName+suffix;
try {
Runtime.getRuntime().exec(cmd);
logger.info("生成长图成功:"+cmd);
} catch (IOException e) {
logger.error("生成长图失败:"+e.getMessage());
}
}
}