采用异步方式,通过任务方式,将次命令丢到消息队列中进行执行
关于wkhtmltopdf的配置(applaction.properties)
#关于wk的配置(生成长图
wk.image.command=D:/wkhtmltopdf/bin/wkhtmltoimage
wk.image.storage=D:/wkData/wk-images
生成主题常量
//主题:分享
String TOPIC_SHARE="share";
wkconfig
在项目第一次启动的时候生成储存对应长图的目录
@Configuration
public class WkConfig {
//在服务启动时生成图片目录
private final 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);
}
}
}
controller
@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;
@RequestMapping(value = "/share", method = RequestMethod.GET)
@ResponseBody
public String shareImage(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);
// eg: http://localhost:8080/community/share/image/33365834673863
return CommunityUtil.getJsonString(0, null, map);
}
//获取长图(直接给浏览器返回一个图片,需要用response处理
@RequestMapping(value = "/share/image/{fileName}", method = RequestMethod.GET)
public void getImage(@PathVariable(name = "fileName") String fileName, HttpServletResponse response) {
if (StringUtils.isBlank(fileName)) {
throw new IllegalArgumentException("文件名不能为空!");
}
response.setContentType("image/png");
//从本地读取文件
File file = new File(wkImageStorage + "/" + fileName + ".png");
try {
OutputStream os = response.getOutputStream();
FileInputStream is=new FileInputStream(file); //文件流:读取文件
byte[] buffer=new byte[1024];
int len=0;
while((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
} catch (IOException e) {
logger.error("获取长图失败:"+e.getMessage());
}
}
}
consumer
//存储路径
@Value("${wk.image.storage}")
private String wkImageStorage;
@Value("${wk.image.command}")
private String wkImageCommand;
@KafkaListener(topics = TOPIC_SHARE)
public void handleShare(ConsumerRecord record){
//先进行判断record是否为空:未发事件或者发送的事件为空
if(record==null|| record.value()==null){
logger.error("发送的消息为空!");
return;
}
//事件不为空:将事件转换为Event对象
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());
}
}