wkhtmltopdf
(1)wkhtmltopdf url file
(1)wkhtmltoimage url file
java
(1)Runtime.getRuntime().exec()
官网https://wkhtmltopdf.org,下载安装,把安装目录添加到环境变量。
新建D:\javing\workspace\data\wk-images和D:\javing\workspace\data\wk-pdfs目录,打开命令窗口,输入
wkhtmltopdf https://www.nowcoder.com d:/work/data/wk-pdfs/1.pdf
就能把牛客网首页以pdf格式保存下来。
若输入
wkhtmltoimage https://www.nowcoder.com d:/work/data/wk-pdfs/1.png
就能把牛客网首页以png格式保存下来。
可以看见图片比较大,有1M多,若要缩小,可以输入
wkhtmltoimage --quality 75 https://www.nowcoder.com d:/work/data/wk-pdfs/2.png
新建WkTests类,
public static void main(String[] args) {
String cmd = "d:/javing/wkhtmltopdf/bin/wkhtmltoimage --quality 75 https://www.nowcoder.com d:/javing/workspace/data/wk-images/3.png";
try {
Runtime.getRuntime().exec(cmd);
System.out.println("ok."); //它交给操作系统后,很快就输出ok(这是异步的)
} catch (IOException e) {
e.printStackTrace();
}
}
可以看到,系统很快返回了ok,等一会才看到3.png生成。
我们可以把这个命令写到application-properties,
# wk
wk.image.command=d:/javing/wkhtmltopdf/bin/wkhtmltoimage
wk.image.storage=d:/javing/workspace/data/wk-images
新建WkConfig类,
private static final Logger logger = LoggerFactory.getLogger(WkConfig.class);
@Value("${wk.image.storage}") //把所配置的生成图片存放路径从application.properties注入进来
private String wkImageStorage;
@PostConstruct
public void init(){
//创建WK图片目录
File file = new File(wkImageStorage);
if(!file.exists()){
file.mkdir();
logger.info("创建WK图片目录:"+wkImageStorage);
}
}
在CommmunityConstant接口类里添加
/**
* 主题:分享
*/
String TOPIC_SHARE = "share";
新建ShareController类,
private static final Logger logger = LoggerFactory.getLogger(ShareController.class);
//事件驱动,controller把这个动作交给事件
@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;
@Value("${qiniu.bucket.share.url}")
private String shareBucketUrl;
//接下来写分享请求
@RequestMapping(path = "/share",method = RequestMethod.GET)
@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);
map.put("shareUrl",shareBucketUrl+"/"+fileName);
return CommunityUtil.getJSONString(0,null,map);
}
在EventConsumer类里,添加
@Value("${wk.image.command}")
private String wkImageCommand;
@Value("${wk.image.storage}")
private String wkImageStorage;
//消费分享事件
@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());
}
}
在ShareController类里添加
//获取长图
@RequestMapping(path = "/share/image/{fileName}",method = RequestMethod.GET)
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 {
OutputStream os = response.getOutputStream();
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int b = 0;
while((b=fis.read(buffer))!=-1){
os.write(buffer,0,b);
}
} catch (IOException e) {
logger.error("获取长图失败:"+e.getMessage());
}
}
这样在浏览网站时,在地址栏加上share?和网址,回车就能生成长图。