Java富文本编辑之图片链接本地化作者:邵发 本文介绍在图文混编项目中(博客、新闻等),如何将富文本中的图片外链转为本地链接的问题。本文是Java学习指南系列教程的官方配套文档,项目源码在本文末尾说明。 所谓富文本Rich Text,就是以HTML形式表示的文本。在前端通常由富文本编辑器得到,比如UEditor,KindEditor,wangEditor等富文本编辑器。在富文本中可能存在外链的图片链接,那么后台如何将外链图片转为本站链接,是本文要讨论的话题。 1. 富文本编辑器在需要实现图文混排功能时,可以使用前端的富文本编辑器。常见的富文本编辑器有 UEditor, KindEditor, wangEditor等,使用起来大同小异。比如,下图以KindEditor来演示。 在提交给后台时,可以调用编辑器提供的API来获取编辑器里面的HTML文本,里面包含了CSS样式和图片链接。关于富文本编辑器的使用,不在本文中详述。 2. 富文本中的图片外链当富文本中包含了图片外链接,一般要求将外链转换为本站链接。 例如以下文本: <p> 根据外媒报道,12月6日,美国海军最新的两栖攻击舰“美国”号抵达了日本佐世保,加入了美国海军第七舰队。</p> <p style='text-align:center'> <img src='https://sinaimg.cn/mil/crawl/116/w550h366/20191210/b48a-ikn7476.jpg'> </p> 后台应该处理这一段HTML,找到<img>元素的src属性,将其外链的图片转为本站链接。在HTML中可能包含了多个图片<img>,因而这里需要使用正则表达式,找到所有的<img>进行处理。 2.1 正则替换使用正则表达式来寻找 src 属性并不难,例如定义一个正则表达式来匹配src属性。 String regex = "src=['\"](.*?)['\"]"; 关于Java中的正则表达式的用法,可以参考Java学习指南系列教程中的《项目应用篇》中的讲解。 现在,需要用此正则表达式,将HTML中的所有src属性找出来。将外链转换为本站链接,再替换回去。在LocalImgSrc.process()中,演示了正则替换的基本写法: String regex = "src=['\"](.*?)['\"]"; Pattern pattern = Pattern.compile(regex); Matcher m = pattern.matcher(html); StringBuffer sb = new StringBuffer(); while( m.find()) { String url = m.group(1); // 外链URL String newUrl = localize(url); // 本地化 String newSrc = String.format(" src='%s' ", newUrl); // 新的src属性 m.appendReplacement(sb, escapeDollar(newSrc)); // 替换回去 } m.appendTail(sb); String result = sb.toString(); 需要注意的是,在调用appendReplacement(sb, str)时要求对str中的$字符进行转义,因为$在正则语境下有特殊语义。这里使用escapeDollar()方法对其转义,将$转义为\$。 2.2 外链图片的本地化所谓的本地化,将是将外链图片下载到本站服务器上,并生成一个本站URL。比如。 外链图片: <img src='https://sinaimg.cn/mil/crawl/116/w550h366/20191210/b48a-ikn7476.jpg' > 本地化: <img src="/demo/tmp/test/1576029683983001.jpg" > 在演示项目中,在服务器上指定一个目录用于存储图片,称为Store目录。为演示方便,直接使用WebRoot下的tmp目录作为Store目录。在执行本地化时,只需要将图片下载到Store目录,然后拼凑出相应的URL即可。 例如, 1 将图片下载到WebRoot\tmp\test\ 目录下,命名为1576029683983001.jpg 2 生成该图片对应的本站链接 /demo/tmp/test/1576029683983001.jpg 详见 LocalImgSrc.localize()方法,代码如下。 private String localize(String imageUrl) throws Exception { ......略 ...... //外链图片本地化处理 String newName = guid.gen() + suffix; String filePath = storePath + newName; File storeDir = store.fileOfPath(storePath); String localUrl = store.urlOfPath(filePath); System.out.println("图片本地化:" + imageUrl + " -> " + localUrl); try { http.download(imageUrl, storeDir, newName, 2*1000000); }catch(Exception e) { System.out.println("无法下载图片URL:" + imageUrl + "," + e.getMessage()); return imageUrl; } return localUrl; } 其中,FileStore是一个工具类,提供URL地址与存储路径之间的转换功能。 3. 项目源码3.1 演示页面演示页面仍然是 http://127.0.0.1:8080/demo/test ,以Spring MVC实现。 后台:TestController.test() 前端:/WebRoot/template/test.html 其中,在前端页面 test.html里包含了KindEditor富文本编辑的支持。 3.2 富文本处理当用户在页面里点‘保存’按钮时,将富文本传到后台,后台在TestController. update()中处理这个请求,将外链图片本地化。代码如下。 @PostMapping("/blog/update.do") public Object update(@RequestBody JSONObject jreq , HttpSession session) throws Exception { //取得用户的输入 String title = jreq.getString("title"); String content = jreq.getString("content"); //将HTML中的图片链接本地化 LocalImgSrc lm = new LocalImgSrc(tmpStore, "/test/"); try{ content = lm.process( content); }finally { lm.destroy(); } //模拟更新到数据库 BlogDB.update(title, content); //返回OK return new AfRestData(""); } 其中,lm.process()为核心方法。直接调用LocalImgSrc工具类,将HTML中的图片外链本地化,然后将转换后的HTML存储到服务器系统中。在真正的项目中可能需要存到数据库里,这里的数据库类BlogDB仅仅是演示模拟。 在转换之后,富文本HTML中的<img>元素就统一为本站链接。本站的演示项目源码可以在此处获取。更多技术请参考Java学习指南系列的其他课程。 |
|