企业网站建设合同书模板,东莞招聘网站,普通的旧房装修价格,中国软件邮箱登录入口需求
用户可以选择以长图的形式分享本网页
方法
wkhtmltopdf wkhtmltopdf url filewkhtmltoimage url file java Runtime.getRuntime().exec()
下载
直接去官网下载对应的版本#xff1a;官网
命令行使用WK wkhtmltopdf https://www.nowcoder.com /opt/project/…需求
用户可以选择以长图的形式分享本网页
方法
wkhtmltopdf wkhtmltopdf url filewkhtmltoimage url file java Runtime.getRuntime().exec()
下载
直接去官网下载对应的版本官网
命令行使用WK wkhtmltopdf https://www.nowcoder.com /opt/project/java/mycommunity-pdfs/1.pdf
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done wkhtmltoimage https://www.nowcoder.com /opt/project/java/mycommunity-images/1.png
Loading page (1/2)
Rendering (2/2)
Done// 上面那条命令生成的长图太大了可以使用下面这条以75%的质量输出wkhtmltoimage --quality 75 https://www.nowcoder.com /opt/project/java/mycommunity-images/1.png
Loading page (1/2)
Rendering (2/2)
Done在java中调用
application.properties
mycommunity.path.domainhttp://localhost:8080
server.servlet.context-path/myCommunity
# WK
wk.image.command/usr/local/bin/wkhtmltoimage
wk.image.storage/opt/project/java/mycommunity-images/WK配置类在每次程序开始运行时自动生成存放图像的文件夹
Configuration
public class WkConfig {private static final Logger logger LoggerFactory.getLogger(WkConfig.class);Value(${wk.image.storage})private String wkImageStorage;PostConstructpublic void init(){// create the dic about WKimageFile file new File(wkImageStorage);if(!file.exists()){file.mkdir();logger.info(create the dictionary of WKimage: wkImageStorage);}}
}调用WK的控制层因为生成长图比较耗时所以使用异步操作在用户操作时调用Kafka的生产者生成事件通知消费者
Controller
public class ShareController implements CommunityConstant {private static final Logger logger LoggerFactory.getLogger(ShareController.class);Autowiredprivate EventProducer eventProducer;Value(${mycommunity.path.domain})private String domain;Value(${server.servlet.context-path})private String contextPath;Value(${wk.image.storage})private String wkImageStorage;GetMapping(path /share)ResponseBodypublic String share(String htmlUrl){// generate the file nameString fileName CommunityUtil.generateUUID();// Asynchronous generation long picEvent event new Event().setTopic(TOPIC_SHARE).setData(htmlUrl, htmlUrl).setData(fileName, fileName).setData(suffix, .png);eventProducer.fireEvent(event);MapString, Object map new HashMap();map.put(shareUrl, domain contextPath /share/image fileName);return CommunityUtil.getJSONString(0, null, map);}//GetMapping(path /share/image/{fileName})public void getShareImage(PathVariable(fileName) String fileName, HttpServletResponse response){if(StringUtils.isBlank(fileName)){throw new IllegalStateException(the file name cannot be blank);}response.setContentType(image/png);File file new File(wkImageStorage / fileName .png);try {OutputStream os response.getOutputStream();FileInputStream fis new FileInputStream(file);byte[] data new byte[1024];int len 0;while ((len fis.read(data)) ! -1) {os.write(data, 0, len);}} catch (IOException e) {logger.error(querty the long image failed: , e.getMessage());}}
}Kafka的消费者定义如何消费生成长图的事件
Component
public class EventConsumer implements CommunityConstant {Autowiredprivate static final Logger logger LoggerFactory.getLogger(EventConsumer.class);Value(${wk.image.storage})private String wkImageStorage;Value(${wk.image.command})private String wkImageCommand;KafkaListener(topics {TOPIC_SHARE})public void handleShareMessage(ConsumerRecord record) {if (record null || record.value() null) {logger.error(the content of the message is empty);return;}Event event JSONObject.parseObject(record.value().toString(), Event.class);if (event null) {logger.error(message format 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(generate long image successfully: cmd);} catch (IOException e) {logger.info(generate long image fail: e.getMessage());}}
}测试