项目1在线交流平台-7.构建安全高效的企业服务-8.kafak应用3-分享html页面为长图


参考牛客网高级项目教程

功能需求

在这里插入图片描述

  • 1.使用wkhtmltopdf软件,可以实现将指定的url网页内容转为pdf文件或图片文件
  • 2.熟悉使用spring客户端操作软件,分享长图,为今后社区的分享功能做准备
  • 3.kafak应用的第三个场景:将请求放进kafka,异步制成长图保存到制定文件夹中

一、wkhtmltopdf基本操作

1. 下载安装,配置环境变量

在这里插入图片描述

2. 默认不会创建文件夹,先创建生成文件的位置

在这里插入图片描述

3. 在cmd中输入命令,测试

生成pdf文件
wkhtmltopdf https://www.nowcoder.com E:/javaWeb/data/wk-pdf/1.pdf

在这里插入图片描述

生成压缩图片
wkhtmltoimage --quality 75 https://www.nowcoder.com E:/javaWeb/data/wk-image/1.png

在这里插入图片描述

二、使用java操作

1. 直接操作命名

Runtime.getRuntime().exec(cmd)
  • 异步加载生成图片
public class WkTests {
    public static void main(String[] args) {
        String cmd = "E:/javaWeb/wkhtmltopdf/bin/wkhtmltoimage --quality 75  https://www.nowcoder.com E:/javaWeb/data/wk-image/2.png";
        try {
            Runtime.getRuntime().exec(cmd);
            System.out.println("ok.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
ok.

在这里插入图片描述

2. Spring中配置路径

自定义配置-今后迁移到linux系统方便修改
# wk
wk.image.command=E:/javaWeb/wkhtmltopdf/bin/wkhtmltoimage
wk.image.storage=E:/javaWeb/data/wk-image
写一个可以自动生成文件夹的配置类
  • 这样,如果没有建文件夹,程序可以自动创建文件夹
file.mkdir()-创建文件夹
@Configuration
public class WkConfig {

    private static final 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);
        }
    }

}

在这里插入图片描述

三、使用服务端请求分享生成长图

1. 在controller层处理分享请求

  • 有前面的命令可知,软件启动命名和文件保存路径均已经配置
  • 自定义的是:动态访问的html的url,以及制作成长图的文件名和后缀名
@Controller
public class ShareController implements CommunityConstant {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Autowired
    EventProducer eventProducer;
    
    @Value("${community.path.domain}")
    String domain;
    
    @Value("${server.servlet.context-path}")
    String contextPath;
    
    @Value("${wk.image.storage}")
    String imageStorage;

    /**
     * 处理分享的异步请求-将请求处理放进kafka,异步消费制成图片
     * @param htmlUrl   域名后输入要分享的网页url-将此网页制成长图
     * @return          返回带有完整访问路径的json信息
     */
    @RequestMapping(path = "/share", method = RequestMethod.GET)
    @ResponseBody
    public String share(String htmlUrl) {
        // 1.图片名称随机-防止命名重复冲突
        String fileName = CommunityUtil.generateUUID();

        // 2.将制作长图的信息和命令发布到kafka消息队列中
        Event event = new Event()
                .setTopic(TOPIC_SHARE)
                .setData("htmlUrl", htmlUrl)
                .setData("fileName", fileName)
                .setData("suffix", ".png");
        eventProducer.sendEvent(event);
        
        // 3. 将访问的路径用json格式返回到页面,以便可以点击显示制作的长图
        Map<String, Object> map = new HashMap<>();
        map.put("shareUrl", domain + contextPath + "/share/image/" + fileName);

        return CommunityUtil.getJSONString(0, null, map);
    }
}

2. 定义kafak消费事件

  • 获取消息中的数据和配置文件的启动命令、文件夹保存路径,拼接操作的命令cmd
/**
 * 消费分享制成长图的消息-将指定url制成长图保存到指定文件中
 */
@KafkaListener(topics = TOPIC_SHARE)
public void handleShareMessage(ConsumerRecord record) {
    // 1.边界条件:先检查有无取到消息
    if (record == null || record.value() == null) {
        logger.error("消息的内容为空!");
        return;
    }
    
    // 2.将拿到的消息恢复成Object类型,方便操作
    Event event = JSONObject.parseObject(record.value().toString(), Event.class);
    if(event == null) {
        logger.error("消息的格式错了!");
        return;
    }
    
    // 3.将访问的网页url制作长图保存到指定文件中
    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());
    }
    
}
测试结果

在这里插入图片描述

在这里插入图片描述

3. Controller获取长图的请求

/**
 * 显示长图的请求
 * @param fileName      图片的文件名
 * @param response      服务器响应中向浏览器写图片
 */
@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());
    }
}
测试结果

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值