From 96672852aee836cf3130e4658f976eab415e2eac Mon Sep 17 00:00:00 2001 From: WangHao <43278047@qq.com> Date: Thu, 27 Aug 2020 21:51:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B9=A6=E7=AD=BE=E5=AF=BC=E5=85=A5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbookmark/BrowserController.java | 132 ++ ruoyi-admin/src/main/resources/logback.xml | 14 +- ruoyi-common/pom.xml | 12 + .../common/utils/BookmarkHtml/Const.java | 38 + .../common/utils/BookmarkHtml/ImportHtml.java | 363 +++++ ruoyi-ui/src/router/index.js | 7 + .../src/views/bookmark/common/ImportHtml.vue | 175 +++ ruoyi-ui/src/views/bookmark/index/index.vue | 6 +- ruoyi-ui/src/views/system/user/index.vue | 1336 ++++++++--------- 9 files changed, 1407 insertions(+), 676 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/yunbookmark/BrowserController.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/Const.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/ImportHtml.java create mode 100644 ruoyi-ui/src/views/bookmark/common/ImportHtml.vue diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/yunbookmark/BrowserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/yunbookmark/BrowserController.java new file mode 100644 index 000000000..9761ea7dc --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/yunbookmark/BrowserController.java @@ -0,0 +1,132 @@ +package com.ruoyi.web.controller.yunbookmark; + + + +import com.ruoyi.bookmark.domain.SqBookmark; +import com.ruoyi.bookmark.domain.SqMenu; +import com.ruoyi.bookmark.service.ISqBookmarkService; +import com.ruoyi.bookmark.service.ISqMenuService; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.BookmarkHtml.ImportHtml; +import com.ruoyi.common.utils.StringUtils; +import org.jsoup.HttpStatusException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import javax.net.ssl.SSLHandshakeException; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + + +/** + * @Auther: Wang + * @Date: + * 功能描述: 导入书签 导出书签 + */ + +@RestController +@RequestMapping("/IO") +public class BrowserController extends BaseController { + public static Logger logger = LoggerFactory.getLogger(BrowserController.class); + + @Autowired + private ISqMenuService iSqMenuService; + @Autowired + private ISqBookmarkService iSqBookmarkService; + + + + @RequestMapping("/import") + @PreAuthorize("@ss.hasPermi('bookmark:bookmark:list')") + public AjaxResult importCollect(@RequestParam("htmlFile") MultipartFile htmlFile){ + logger.debug("开始上传状态是:"); + + SysUser sysUser=getAuthUser(); + Long userID= sysUser.getUserId(); + + + try { + Map> map = ImportHtml.parseHtml(htmlFile.getInputStream()); + // Map> map = ImportHtml.importHtmlMore(htmlFile.getInputStream()); + if(null == map || map.isEmpty()){ + logger.info("未获取到url连接"); + return AjaxResult.error("未获取到url连接,空书签"); + } + + + for (Entry> entry : map.entrySet()) { + String favoritesName = entry.getKey(); + //添加目录 + SqMenu sqMenu=new SqMenu(); + sqMenu.setUserId(userID); + sqMenu.setCreateTime(new Date()); + sqMenu.setMenuName(favoritesName); + sqMenu.setParentId(0L); + iSqMenuService.insertSqMenu(sqMenu); + + + importHtml(entry.getValue(), sqMenu.getMenuId(), userID); + } + + }catch (SSLHandshakeException e){ + logger.error("文章解析出错:",e); + } + catch (DataIntegrityViolationException e){ + logger.error("导入存储异常:",e); + } + catch (HttpStatusException a){ + logger.error("文档解析错误:",a); + } + catch (Exception e) { + logger.error("导入html异常:",e); + } + + return AjaxResult.success("导入成功"); + } + + + + /** + * 导入收藏文章 + */ + public void importHtml(Map map,Long menuID,Long userId){ + for(Entry entry : map.entrySet()){ + try { + //获取URL后查询最新的URL信息 + Map result = ImportHtml.getCollectFromUrl(entry.getKey()); + SqBookmark sqBookmark =new SqBookmark(); + sqBookmark.setUserid(userId); + sqBookmark.setTitle(entry.getValue()); + sqBookmark.setUrl(entry.getKey()); + sqBookmark.setUrls(ImportHtml.Urlutils(new URL(entry.getKey()))); + if(StringUtils.isBlank(result.get("description"))){ + sqBookmark.setDescription(entry.getValue()); + }else{ + sqBookmark.setDescription(result.get("description")); + } + sqBookmark.setMenuId(menuID); + sqBookmark.setCreateTime(new Date()); + iSqBookmarkService.insertSqBookmark(sqBookmark); + } catch (Exception e) { + logger.error("导入存储异常:",e); + } + } + + } + + + +} diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml index d69a57207..5e81dbb5e 100644 --- a/ruoyi-admin/src/main/resources/logback.xml +++ b/ruoyi-admin/src/main/resources/logback.xml @@ -11,7 +11,7 @@ ${log.pattern} - + ${log.path}/sys-info.log @@ -34,7 +34,7 @@ DENY - + ${log.path}/sys-error.log @@ -56,7 +56,7 @@ DENY - + ${log.path}/sys-user.log @@ -70,7 +70,7 @@ ${log.pattern} - + @@ -79,15 +79,15 @@ - + - + - \ No newline at end of file + diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index b5ee531b8..048037eb2 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -125,6 +125,18 @@ 2.1.5 + + + org.jsoup + jsoup + 1.13.1 + + + + org.apache.commons + commons-lang3 + 3.5 + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/Const.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/Const.java new file mode 100644 index 000000000..17c796bdd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/Const.java @@ -0,0 +1,38 @@ +package com.ruoyi.common.utils.BookmarkHtml; + +import org.springframework.stereotype.Component; + +/** + * @Auther: Wang + * @Date: 2020/08/22 23:03 + * 功能描述: + */ +@Component +public class Const { + + public static String BASE_PATH; + + public static String LOGIN_SESSION_KEY = "Favorites_user"; + + public static String PASSWORD_KEY = "@#$%^&*()OPG#$%^&*(HG"; + + public static String DES3_KEY = "9964DYByKL967c3308imytCB"; + + public static String default_logo="img/logo.jpg"; + + public static String userAgent="Mozilla"; + + public static String default_Profile=BASE_PATH+"/img/logo.jpg"; + + public static String LAST_REFERER = "LAST_REFERER"; + + public static int COOKIE_TIMEOUT= 30*24*60*60; + + +// @Autowired(required = true) +// public void setBasePath(@Value("${favorites.base.path}")String basePath) { +// Const.BASE_PATH = basePath; +// } + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/ImportHtml.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/ImportHtml.java new file mode 100644 index 000000000..fb2963a2b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BookmarkHtml/ImportHtml.java @@ -0,0 +1,363 @@ +package com.ruoyi.common.utils.BookmarkHtml; + + +import com.ruoyi.common.utils.StringUtils; +import org.jsoup.Connection; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @Auther: Wang + * @Date: 2020/08/22 22:56 + * 功能描述: + */ +public class ImportHtml { + + public static Logger logger = LoggerFactory.getLogger(ImportHtml.class); + /** + * @param url + * @return + */ +// public static String getImge(String url){ +// String logo=""; +// logo=getPageImg(url); +// if(StringUtils.isBlank(logo) || logo.length()>300){ +// logo=Const.BASE_PATH + Const.default_logo; +// } +// return logo; +// } + + /** + * @param url + * @return + */ +// public static String getPageImg(String url){ +// String imgUrl=""; +// Document doc; +// try { +// doc = Jsoup.connect(url).userAgent(Const.userAgent).get(); +// Elements images = doc.select("img[src~=(?i)\\.(png|jpe?g|gif)]"); +// for(Element image : images){ +// imgUrl=image.attr("src"); +// if(StringUtils.isNotBlank(imgUrl) ){ +// if(imgUrl.startsWith("//")){ +// imgUrl = "http:" + imgUrl; +// }else if(!imgUrl.startsWith("http") && !imgUrl.startsWith("/")){ +// imgUrl=URLUtil.getDomainUrl(url) + "/" + imgUrl; +// }else if(!imgUrl.startsWith("http")){ +// imgUrl=URLUtil.getDomainUrl(url)+imgUrl; +// } +// } +// // 判断图片大小 +// String fileUrl = download(imgUrl); +// if(fileUrl!=null){ +// File picture = new File(fileUrl); +// FileInputStream in = new FileInputStream(picture); +// BufferedImage sourceImg = ImageIO.read(in); +// String weight = String.format("%.1f",picture.length()/1024.0); +// int width = sourceImg.getWidth(); +// int height = sourceImg.getHeight(); +// // 删除临时文件 +// if(picture.exists()){ +// in.close(); +// picture.delete(); +// } +// if(Double.parseDouble(weight) <= 0 || width <=0 || height <= 0){ +// logger.info("当前图片大小为0,继续获取图片链接"); +// imgUrl=""; +// }else{ +// break; +// } +// } +// } +// } catch (Exception e) { +// +// logger.warn("getPageImg 失败,url:"+url,e.getMessage()); +// } +// return imgUrl; +// } + /** + * @auther: Wang + * @date: 2020/02/14 15:35 + * 功能描述:查询URL的 最新信息 + */ + + public static Map getCollectFromUrl(String url){ + Map result = new HashMap(); + try { + result.put("url", url); + + Connection connection = Jsoup.connect(url).userAgent(Const.userAgent); + connection.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + connection.header("Accept-Encoding", "gzip, deflate, sdch"); + connection.header("Accept-Language", "zh-CN,zh;q=0.8"); + connection.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"); + Document doc = connection.get(); + String title = doc.title(); + if(StringUtils.isNotBlank(title)){ + result.put("title", title); + } + String charset = doc.charset().name(); + if(StringUtils.isBlank(charset)){ + Elements eles = doc.select("meta[http-equiv=Content-Type]"); + Iterator itor = eles.iterator(); + while (itor.hasNext()){ + charset = matchCharset(itor.next().toString().toUpperCase()); + } + } + if(StringUtils.isBlank(charset)){ + result.put("charset", charset); + } + Elements metas = doc.head().select("meta"); + for (Element meta : metas) { + String content = meta.attr("content"); + if ("description".equalsIgnoreCase(meta.attr("name"))) { + result.put("description", content); + } + } + //result.put("logoUrl", getImge(url)); + } catch (Exception e) { + logger.error("文章解析出错:",e); + } + return result; + } +// + /** + * 一层,只输出url及对应的title或描述 + * @param in + * @return + */ + public static Map parseHtmlOne(InputStream in){ + Map map = new HashMap(); + try { + Document doc = Jsoup.parse(in, "UTF-8", ""); + Elements metas = doc.select("a"); + for (Element meta : metas) { + String url = meta.attr("href"); + if(url.startsWith("http")){ + map.put(url, meta.text()); + } + } + } catch (Exception e) { + logger.error("解析html 文件异常:",e); + } + return map; + } + + /** + * 两层(文件夹) + * @param HTML + * @return + */ + public static Map> parseHtml(InputStream HTML){ + Map> resultMap = new HashMap>(); + try { + Document doc = Jsoup.parse(HTML, "UTF-8", ""); + Elements metasdts = doc.select("dt"); + for(Element dt : metasdts){ + String favoritesName = ""; + Elements dtcs = dt.children(); + Map map = new HashMap(); + for(Element dt1 : dtcs){ + if("h3".equalsIgnoreCase(dt1.nodeName())){ + favoritesName = dt1.text(); + }else if("dl".equalsIgnoreCase(dt1.nodeName())){ + Elements dts = dt1.children(); + for(Element dt11 : dts){ + if("dt".equals(dt11.nodeName())){ + if("a".equals(dt11.child(0).nodeName())){ + String url = dt11.child(0).attr("href"); + if(url.startsWith("http")){ + map.put(url, dt11.child(0).text()); + } + } + } + } + } + } + if(StringUtils.isNotBlank(favoritesName) && map.size() > 0){ + resultMap.put(favoritesName, map); + } + } + } catch (Exception e) { + logger.error("解析html文件异常:",e); + } + return resultMap; + } + + /** + * 按照文档结构输出(TODO) + */ + public static Map> importHtmlMore(InputStream in){ + Map> resultMap = new HashMap>(); + try { + Document doc = Jsoup.parse(in, "UTF-8", ""); + Elements bodys = doc.child(0).children(); + + for(Element body : bodys){ + if("body".equalsIgnoreCase(body.nodeName())){ + Elements dls = body.children(); + for(Element dl : dls){ + if("dl".equalsIgnoreCase(dl.nodeName())){ + resultMap = parseElements(dl,resultMap); + System.out.println("resultMap:" + resultMap); + } + } + } + } + + + } catch (Exception e) { + logger.error("解析html文件异常:",e); + } + return resultMap; + } + + public static Map> parseElements(Element element,Map> resultMap){ + Map favoritesMap = new HashMap(); + Map urlMap = new HashMap(); + String favoritesName = ""; + Elements dts = element.children(); + for(Element dt : dts){ + if("dt".equalsIgnoreCase(dt.nodeName())){ + Elements dtas = dt.children(); + for(Element a : dtas){ + if("a".equalsIgnoreCase(a.nodeName())){ + String url = a.attr("href"); + if(url.startsWith("http")){ + urlMap.put(url, a.text()); + favoritesName=a.parent().parent().parent().child(0).text(); + System.out.println("目录:"+favoritesName); + logger.error("目录:",favoritesName); + } + }else if("dl".equalsIgnoreCase(a.nodeName())){ + resultMap = parseElements(a,resultMap); + } + } + + } + } + if(StringUtils.isNotBlank(favoritesName)){ + favoritesMap.put(favoritesName, urlMap); + } + List mapList = null; + Element parment = element.parent().parent().parent().child(0); + if("h3".equalsIgnoreCase(parment.nodeName())){ + String name = parment.text(); + if(resultMap.containsKey(name)){ + mapList = resultMap.get(name); + mapList.add(favoritesMap); + }else{ + mapList = new ArrayList(); + mapList.add(favoritesMap); + } + resultMap.put(name, mapList); + } + return resultMap; + } + +// public static StringBuilder exportHtml(String title,StringBuilder body){ +// StringBuilder sb = new StringBuilder(); +// sb.append(""); +// sb.append(""); +// sb.append(""+title+""); +// sb.append(""); +// sb.append(""); +// sb.append("

"+title+"

"); +// sb.append(body); +// sb.append(""); +// +// return sb; +// } +// + public static String matchCharset(String content) { + Pattern p = Pattern.compile("(?<=charset=)(.+)(?=\")"); + Matcher m = p.matcher(content); + if (m.find()){ + return m.group(); + } + return null; + } +// +// // 图片下载 +// private static String download(String url) { +// try { +// String imageName = url.substring(url.lastIndexOf("/") + 1, +// url.length()); +// +// URL uri = new URL(url); +// InputStream in = uri.openStream(); +// String dirName = "static/temp/"; +// File dirFile = new File(dirName); +// if(!dirFile.isDirectory()){ +// dirFile.mkdir(); +// } +// String fileName = dirName+imageName; +// File file = new File(dirFile,imageName); +// FileOutputStream fo = new FileOutputStream(file); +// byte[] buf = new byte[1024]; +// int length = 0; +// while ((length = in.read(buf, 0, buf.length)) != -1) { +// fo.write(buf, 0, length); +// } +// in.close(); +// fo.close(); +// return fileName; +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } +// +// /** +// * 判断链接是否失效 +// * @param url +// * @return +// */ +// public static boolean isConnect(String url){ +// HttpURLConnection connection; +// int counts = 0; +// boolean flag = false; +// if (url == null || url.length() <= 0) { +// return flag; +// } +// while (counts < 5) { +// try { +// connection = (HttpURLConnection) new URL(url).openConnection(); +// int state = connection.getResponseCode(); +// if (state == 200) { +// flag = true; +// } +// break; +// } catch (Exception e) { +// counts++; +// continue; +// } +// } +// return flag; +// } + + + // /** +// * @auther: Wang +// * @date: 2020/02/15 14:44 +// * 功能描述:分割书签URL 得到官网主机 +// * @return +// */ + public static String Urlutils(URL url) throws MalformedURLException { + String host = url.getHost();// 获取主机名 + return host; + } +} diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 340a6f459..a184caa69 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -159,6 +159,13 @@ export const constantRoutes = [ meta:{ requireAuth: false,//加该字段,表示进入这个路由是需要登录的true }, + },{ + path: '/importHtml', + name: 'importHtml', + component: resolve => require(['../views/bookmark/common/ImportHtml.vue'], resolve), + meta:{ + requireAuth: true,//加该字段,表示进入这个路由是需要登录的true + }, } ], diff --git a/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue b/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue new file mode 100644 index 000000000..56a6472d6 --- /dev/null +++ b/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue @@ -0,0 +1,175 @@ + + + + + diff --git a/ruoyi-ui/src/views/bookmark/index/index.vue b/ruoyi-ui/src/views/bookmark/index/index.vue index 837cfbb9c..8d01156bf 100644 --- a/ruoyi-ui/src/views/bookmark/index/index.vue +++ b/ruoyi-ui/src/views/bookmark/index/index.vue @@ -24,7 +24,11 @@
工具箱
收藏同步
发现书签
-
任意门
+ +
+ 导入书签 +
+
收件箱
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index 51c262731..f5783e888 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -1,668 +1,668 @@ - - - \ No newline at end of file + + +