完成书签的导出和自动备份到百度云

This commit is contained in:
WangHao 2021-11-20 02:15:27 +08:00
parent 7e0ba54813
commit cd55a8b2a5
29 changed files with 2142 additions and 461 deletions

View File

@ -102,7 +102,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<!-- <version>2.1.1.RELEASE</version>-->
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>

View File

@ -76,9 +76,9 @@ public class SqBookmarkController extends BaseController
startPage();
List<SqBookmark> list = sqBookmarkService.selectByUrlUserID(url,getAuthUser().getUserId());
if (list!=null&&!list.isEmpty()){
return AjaxResult.success(list.get(0));
return AjaxResult.success(true);
}
return AjaxResult.success(list);
return AjaxResult.success(false);
}
@ -201,6 +201,17 @@ public class SqBookmarkController extends BaseController
return toAjax(sqBookmarkService.deleteSqBookmarkByIds(bookmarkIds));
}
/**
* 删除书签 根据URL删除
*/
@PreAuthorize("@ss.hasPermi('bookmark:bookmark:common:remove')")
@DeleteMapping("/deleteByurl")
public AjaxResult deleteByurl(String url)
{
return AjaxResult.success("success");
// return sqBookmarkService.deleteByUrl(getAuthUser().getUserId(),url);
}
/**
* 用户-根据标签查询书签分页

View File

@ -1,143 +0,0 @@
package com.ruoyi.web.test.controller;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.baidu.servise.BaiduWangPanServise;
import com.ruoyi.common.constant.BaiduUrl;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.*;
import java.util.HashMap;
/**
* @Auther: Wang
* @Date: 2021/07/24 22:37
* 功能描述:
* //教程
* //https://blog.csdn.net/admans/article/details/80653490
*/
public class BaiDuWangPan extends BaseSpringBootTest{
@Autowired
private BaiduWangPanServise baiduWangPanServise;
private static String access_token = "123.5f2c72c8c2106a3baa177de77331b1d1.YnelNhviWQotgsooAt63iCRbaqZrjEP0Qgj3nIx.jMfNkQ";
// 获取用户信息
@Test
public void getUser() {
String result = baiduWangPanServise.getUserInfo(access_token);
JSONObject object = JSONObject.parseObject(result);
System.out.println("result" + result);
System.out.println("baidu_name:" + object.get("baidu_name"));
System.out.println("netdisk_name:" + object.get("netdisk_name"));
}
// 获取容量
@Test
public void getCapacity() {
String result = baiduWangPanServise.getCapacity(access_token);
System.out.println("result" + result);
}
// 上传文件
@Test
public void addFile() {
//预上传分片上传创建文件
String md5 = "";
try {
md5 = DigestUtils.md5Hex(new FileInputStream(new File("D:\\Wang\\22.txt")));
} catch (IOException e) {
e.printStackTrace();
}
//预上传 获取ID
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("access_token", access_token);
paramMap.put("path", "/apps/藏趣云/22.txt");
paramMap.put("size", "1");//文件或目录的大小单位B
paramMap.put("isdir", "0");//是否目录0 文件1 目录
paramMap.put("block_list", "[\"" + md5 + "\"]");
paramMap.put("autoinit", 1);
String result = HttpUtil.post("https://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token" + access_token, paramMap);
System.out.println("result" + result);
JSONObject object = JSONObject.parseObject(result);
String uploadid = object.getString("uploadid");
System.out.println("uploadid" + uploadid);
//上传文件
HashMap<String, Object> paramMap1 = new HashMap<>();
// paramMap1.put("file", ReadFileToCharArray("D:\\Wang\\22.txt"));
paramMap1.put("file", new File("D:\\Wang\\22.txt"));
System.out.println("file" + paramMap1.get("file").toString());
// String result2 = HttpUtil.post("https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?access_token=" + access_token + "&method=upload&type=tmpfile&path=%2Fapps%2F%E8%97%8F%E8%B6%A3%E4%BA%91%2F22.txt&partseq=0&uploadid=" + uploadid, paramMap1);
// System.out.println("result2" + result2);
String url = Constant.SLICING_UPLOAD_FILE_URL + "?method=upload" +
"&access_token=" + Constant.ATOKEN +
"&type=tmpfile&partseq=0" +
"&path=" + Constant.APP_PATH + "22.txt" +
"&uploadid=" + uploadid;
String result2 = FileUtilsBaidu.sendFile(url,new File("D:\\Wang\\22.txt"));
System.out.println("result2" + result2);
//创建文件
HashMap<String, Object> paramMap3 = new HashMap<>();
// paramMap1.put("file", ReadFileToCharArray("D:\\Wang\\22.txt"));
paramMap3.put("path", "/apps/藏趣云/22.txt");
paramMap3.put("size", 6);
paramMap3.put("isdir", 0);
String result3 = HttpUtil.post("https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token=" + access_token, paramMap3);
System.out.println("result3" + result3);
}
//将文件转换成char[]数组
public static char[] ReadFileToCharArray(String filePath) throws IOException {
StringBuilder fileData = new StringBuilder(1000);
BufferedReader reader = new BufferedReader(new FileReader(filePath));
char[] buf = new char[10];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
System.out.println(numRead);
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString().toCharArray();
}
}

View File

@ -1,136 +0,0 @@
package com.ruoyi.web.test.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HtmlUtil;
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.utils.StringUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Auther: Wang
* @Date: 2021/04/19 21:16
* 功能描述:
*/
public class HtmlTest extends BaseSpringBootTest {
@Autowired
private ISqMenuService iSqMenuService;
@Autowired
private ISqBookmarkService iSqBookmarkService;
@Test
public void test3() {
String favoritesId = "2";
if(StringUtils.isNotBlank(favoritesId))
{
HttpServletResponse response=null;
try {
String fileName = "cqy_" + DateUtil.now() + ".html";
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" +
"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n" +
"<TITLE>Bookmarks</TITLE>\n" +
"<H1>Bookmarks</H1>");
sb.append("<DL>\n");
sb.append(exportToHtml(1L));
sb.append("</DL>\n");
//1:使用File类创建一个要操作的文件路径
File file = new File("D:" + File.separator + "demo" + File.separator + fileName);
if(!file.getParentFile().exists()){ //如果文件的目录不存在
file.getParentFile().mkdirs(); //创建目录
}
//2: 实例化OutputString 对象
OutputStream output = new FileOutputStream(file);
//3: 准备好实现内容的输出
//将字符串变为字节数组
byte data[] = sb.toString().getBytes();
output.write(data);
//4: 资源操作的最后必须关闭
output.close();
} catch (Exception e) {
logger.error("异常:", e);
}
}
}
/**
* 导出到html文件
* @param
*/
public StringBuilder exportToHtml(Long userId){
SqMenu sqMenu=new SqMenu();
sqMenu.setUserId(userId);
SqBookmark sqBookmark = new SqBookmark();
sqBookmark.setUserid(userId);
//目录
List<SqMenu> menuList = iSqMenuService.selectSqMenuList(sqMenu);
Map<Long, List<SqMenu>> mapMenu = menuList.stream().collect(Collectors.groupingBy(SqMenu::getParentId));
//书签
List<SqBookmark> bookMarkList = iSqBookmarkService.selectSqBookmarkList(sqBookmark);
Map<Long, List<SqBookmark>> mapBookMark = bookMarkList.stream().collect(Collectors.groupingBy(SqBookmark::getMenuId));
List<SqMenu> sqMenuList = mapMenu.get(0L);
StringBuilder str = new StringBuilder();
str = traverseFile_recursion(sqMenuList,str,mapBookMark,mapMenu);
return str;
}
/**
* @Description:递归书签导出功能
*
* @param * @param sqMenuList
* @param str
* @param mapBookMark
* @param mapMenu
* @return java.lang.StringBuilder
* @Date
* @author: wanghao
*
*/
public StringBuilder traverseFile_recursion (List<SqMenu> sqMenuList,StringBuilder str,Map<Long, List<SqBookmark>> mapBookMark,Map<Long, List<SqMenu>> mapMenu) {
if (sqMenuList != null && !sqMenuList.isEmpty()) {
for (SqMenu f : sqMenuList) {
str.append("<DT><H3 ADD_DATE=\"1584277207\" LAST_MODIFIED=\"0\">").append(f.getMenuName()).append("</H3>\n");
str.append("<DL>\n");
List<SqBookmark> bookmarksList = mapBookMark.get(f.getMenuId());
if (bookmarksList != null && !bookmarksList.isEmpty()) {
for (SqBookmark b : bookmarksList) {
str.append("<DT><A HREF=\""+b.getUrl()+"\" TARGET=\"_blank\">"+b.getTitle()+"</A>\n");
}
}
traverseFile_recursion(mapMenu.get(f.getMenuId()),str,mapBookMark,mapMenu);
str.append("</DL>\n");
}
}
return str;
}
}

View File

@ -0,0 +1,171 @@
package com.ruoyi.web.test.controller.baiduyunpan;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.BackupsYunPan;
import com.ruoyi.baiduyunpan.servise.BaiduWangPanServise;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.web.test.controller.BaseSpringBootTest;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.*;
import java.util.HashMap;
/**
* @Auther: Wang
* @Date: 2021/07/24 22:37
* 功能描述:
* //教程
*
*/
public class BaiDuWangPan extends BaseSpringBootTest {
@Autowired
private BaiduWangPanServise baiduWangPanServise;
@Autowired
private BackupsYunPan backupsYunPan;
private static String access_token = Constant.ATOKEN;
@Test
public void ss(){
//百度 备份
backupsYunPan.BaiDuYunBackups("D:\\data\\ces\\","day4_MySQL性能优化总结.zip",Constant.ATOKEN);
}
// 获取用户信息
@Test
public void getUser() {
String result = baiduWangPanServise.getUserInfo(Constant.ATOKEN);
JSONObject object = JSONObject.parseObject(result);
System.out.println("result" + result);
System.out.println("baidu_name:" + object.get("baidu_name"));
System.out.println("netdisk_name:" + object.get("netdisk_name"));
}
// 获取容量
@Test
public void getCapacity() {
String result = baiduWangPanServise.getCapacity(access_token);
System.out.println("result" + result);
}
// 上传文件
@Test
//预上传 >> 分片上传 >> 创建文件
// 废弃 FileUtilsBaidu 参考这个
public void addFile() {
String fileName = "22.txt";
String userPath = "D:\\Wang\\" + fileName;
String token = Constant.ATOKEN;
//第一步:预上传
//对于大文件 需要吧他分成多份(小于4M)然后计算每份的MD5弄成数组
String md5 = "";
try {
md5 = DigestUtils.md5Hex(new FileInputStream(new File(userPath)));
HashMap<String, Object> postParamMap = new HashMap<>();
postParamMap.put("access_token", token);
postParamMap.put("path", "/apps/藏趣云/22.txt");
postParamMap.put("size", 7);//文件或目录的大小单位B
postParamMap.put("isdir", "0");//是否目录0 文件1 目录
postParamMap.put("block_list", "[\"" + md5 + "\"]");
postParamMap.put("autoinit", 1);
HashMap<String, String> getParamMap = new HashMap<>();
getParamMap.put("method","precreate");
getParamMap.put("access_token",token);
String precreateUrl = HttpUtils.initUriPathParams(Constant.FILE_MANAGER_URL,getParamMap);
String result = HttpUtil.post(precreateUrl, postParamMap);
System.out.println("result" + result);
String uploadid = JSONObject.parseObject(result).getString("uploadid");
System.out.println("uploadid" + uploadid);
//第二步:分片上传
HashMap<String, String> superfile2Map = new HashMap<>();
superfile2Map.put("method", "upload");
superfile2Map.put("access_token", token);
superfile2Map.put("type", "tmpfile");
superfile2Map.put("partseq", "0");
superfile2Map.put("path", Constant.APP_PATH +fileName);
superfile2Map.put("uploadid", uploadid);
System.out.println("superfile2Map"+superfile2Map.values().toString());
String url = HttpUtils.initUriPathParams(Constant.SLICING_UPLOAD_FILE_URL,superfile2Map);
String result2 = FileUtilsBaidu.sendFile(url,new File(userPath));
System.out.println("result2" + result2);
//第三步;创建文件
HashMap<String, Object> postCreateMap = new HashMap<>();
postCreateMap.put("path", "/apps/藏趣云/22.txt");
postCreateMap.put("size", 7);
postCreateMap.put("isdir", 0);
postCreateMap.put("rtype", 2);
postCreateMap.put("uploadid", uploadid);
postCreateMap.put("block_list", "[\"" + md5 + "\"]");
HashMap<String, String> getCreateMap = new HashMap<>();
getParamMap.put("method","create");
getParamMap.put("access_token",token);
String CreateUrl = HttpUtils.initUriPathParams(Constant.FILE_MANAGER_URL,getParamMap);
String result3 = HttpUtil.post(CreateUrl, postCreateMap);
System.out.println("result3" + result3);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//将文件转换成char[]数组
public static char[] ReadFileToCharArray(String filePath) throws IOException {
StringBuilder fileData = new StringBuilder(1000);
BufferedReader reader = new BufferedReader(new FileReader(filePath));
char[] buf = new char[10];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
System.out.println(numRead);
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString().toCharArray();
}
}

View File

@ -0,0 +1,58 @@
package com.ruoyi.web.test.controller.baiduyunpan;
/**
* @Auther: Wang
* @Date: 2021/07/25 02:03
* 功能描述:
*
* 文档API https://www.wenjiangs.com/doc/leikdy8r
*
*/
public interface Constant {
String APP_ID="24066444";
String APP_NAME="藏趣云";
String APP_KEY="7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9";
String SECRET_KEY="RfvvGbkN95CuXlaoZVzzsvGiz9Her6qq";
String SING_key="dBpomXW%duC2L8l6MW3yTpaXhX=-8oj0";
String APP_PATH="/apps/"+APP_NAME+"/";
//https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&redirect_uri=https://www.baidu.com/&scope=basic,netdisk&display=tv&qrcode=1&force_login=1
//https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=0a291eb3fd3ed6ccc74cc46bc5540191&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&client_secret=RfvvGbkN95CuXlaoZVzzsvGiz9Her6qq&redirect_uri=oob
//单位mb
// 普通用户单个分片大小固定为4MB文件大小如果小于4MB无需切片直接上传即可单文件总大小上限为4G
//普通会员用户单个分片大小上限为16MB单文件总大小上限为10G
//超级会员用户单个分片大小上限为32MB单文件总大小上限为20G
Integer UNIT=4;
//获取授权码需要扫码登陆
String GET_CODE_URL="https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id="+APP_KEY+"&redirect_uri=oob&scope=basic,netdisk&display=tv&qrcode=1&force_login=1";
//获取到的授权码
String CODE="0a291eb3fd3ed6ccc74cc46bc5540191";
//根据授权码换取token
String GET_TOKEN_BY_CODE="https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code="+CODE+"&client_id="+APP_KEY+"&client_secret="+SECRET_KEY+"&redirect_uri=oob";
//"refresh_token": "122.035106ef57234db73fa1d6077df6b2a4.YD6wvL7Qcuh-Jsz3KUYhob9bYABdvCAAwf6pX3e.9r3fbA",
//"access_token": "121.1bbdb55745ea8eebdc6fe83f0481c676.YsAIaraM0JxC1aw_DEbopy8wLGK7mdg6mTGeR8Y.6nzOlA",
//获取到的TOKEN
String RTOKEN="122.fec5f9d6dd1644c2c57c89cc510f7ec8.YBMpVZwjo9y5kSMFnVmSMJL9dj25T5X02gjLwV8.1J2sEw";
String ATOKEN="121.1bbdb55745ea8eebdc6fe83f0481c676.YsAIaraM0JxC1aw_DEbopy8wLGK7mdg6mTGeR8Y.6nzOlA";
//操作文件 method = copy, mover, rename, delete
String FILE_MANAGER_URL="https://pan.baidu.com/rest/2.0/xpan/file";
//预上传
String GET_READY_FILE_URL="https://pan.baidu.com/rest/2.0/xpan/file";
//分片上传
String SLICING_UPLOAD_FILE_URL="https://d.pcs.baidu.com/rest/2.0/pcs/superfile2";
//下载文件
String DOWN_LOUE_URL="https://pan.baidu.com/rest/2.0/xpan/multimedia";
//文件搜索
String FILE_SEARCH="https://pan.baidu.com/rest/2.0/xpan/file?method=search";
}

View File

@ -0,0 +1,183 @@
package com.ruoyi.web.test.controller.baiduyunpan;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
/**
* @Auther: Wang
* @Date: 2021/07/25 17:51
* 功能描述:
*/
public class FileSizeUtil {
private static final String TAG=FileSizeUtil.class.getSimpleName();
public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值
/**
* @param @param imgPath
* @param @return 根据图片地址返回图片大小kb或者 Mb
* @return String
* @throws
* @Title: pathSize
* @add (default no)
*/
public static String pathSize(String imgPath) {
File file = new File(imgPath);
FileInputStream fis;
int fileLen = 0;
try {
fis = new FileInputStream(file);
fileLen = fis.available();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return String.valueOf(fileLen);
}
/**
* 获取文件指定文件的指定单位的大小
*
* @param filePath 文件路径
* @param sizeType 获取大小的类型1为B2为KB3为MB4为GB
* @return double值的大小
*/
public static double getFileOrFilesSize(String filePath, int sizeType) {
File file = new File(filePath);
long blockSize = 0;
try {
if (file.isDirectory()) {
blockSize = getFileSizes(file);
} else {
blockSize = getFileSize(file);
}
} catch (Exception e) {
e.printStackTrace();
// LogUtil.E(TAG,"获取文件大小失败!");
}
return FormetFileSize(blockSize, sizeType);
}
/**
* 调用此方法自动计算指定文件或指定文件夹的大小
*
* @param filePath 文件路径
* @return 计算好的带BKBMBGB的字符串
*/
public static String getAutoFileOrFilesSize(String filePath) {
File file = new File(filePath);
long blockSize = 0;
try {
if (file.isDirectory()) {
blockSize = getFileSizes(file);
} else {
blockSize = getFileSize(file);
}
} catch (Exception e) {
e.printStackTrace();
// LogUtil.E(TAG,"获取文件大小失败!");
}
return FormetFileSize(blockSize);
}
/**
* 获取指定文件大小
*
* @param file
* @return
* @throws Exception
*/
private static long getFileSize(File file) throws Exception {
long size = 0;
if (file.exists()) {
FileInputStream fis = null;
fis = new FileInputStream(file);
size = fis.available();
} else {
file.createNewFile();
// LogUtil.E(TAG,"获取文件大小不存在!");
}
return size;
}
/**
* 获取指定文件夹
*
* @param f
* @return
* @throws Exception
*/
private static long getFileSizes(File f) throws Exception {
long size = 0;
File flist[] = f.listFiles();
for (int i = 0; i < flist.length; i++) {
if (flist[i].isDirectory()) {
size = size + getFileSizes(flist[i]);
} else {
size = size + getFileSize(flist[i]);
}
}
return size;
}
/**
* 转换文件大小
*
* @param fileS
* @return
*/
private static String FormetFileSize(long fileS) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
String wrongSize = "0B";
if (fileS == 0) {
return wrongSize;
}
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "KB";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "MB";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "GB";
}
return fileSizeString;
}
/**
* 转换文件大小,指定转换的类型
*
* @param fileS
* @param sizeType
* @return
*/
private static double FormetFileSize(long fileS, int sizeType) {
DecimalFormat df = new DecimalFormat("#.00");
double fileSizeLong = 0;
switch (sizeType) {
case SIZETYPE_B:
fileSizeLong = Double.valueOf(df.format((double) fileS));
break;
case SIZETYPE_KB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));
break;
case SIZETYPE_MB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));
break;
case SIZETYPE_GB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824));
break;
default:
break;
}
return fileSizeLong;
}
}

View File

@ -1,15 +1,13 @@
package com.ruoyi.web.test.controller;
package com.ruoyi.web.test.controller.baiduyunpan;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.ruoyi.web.test.controller.baiduyunpan.Constant;
import com.ruoyi.web.test.controller.baiduyunpan.FileSizeUtil;
import lombok.SneakyThrows;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
@ -18,20 +16,15 @@ import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.velocity.runtime.directive.Foreach;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
/**
* @Auther: Wang
@ -45,8 +38,10 @@ public class FileUtilsBaidu {
public static void main(String[] args) {
//不能有空格
String filePath = "D:\\data\\ces\\";
String fileName = "day4_MySQL性能优化总结.zip";
// String filePath = "D:\\data\\ces\\";
// String fileName = "day4_MySQL性能优化总结.zip";
String filePath = "D:\\Wang\\";
String fileName = "22.txt";
System.out.println(save(filePath, fileName));
}
@ -95,7 +90,7 @@ public class FileUtilsBaidu {
Thread.sleep(3000);
//创建文件
log.info("创建文件 fileName{} 文件大小{} md5:{} ID:{}", fileName,FileSizeUtil.pathSize(absoluteFilePath),md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
log.info("创建文件 fileName{} 文件大小{} md5:{} ID:{}", fileName, FileSizeUtil.pathSize(absoluteFilePath),md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
String create = create(fileName, fileMax, 0, md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
log.info("创建文件{}", create);
@ -112,7 +107,9 @@ public class FileUtilsBaidu {
* @param: fileName 文件名
*/
private static String getDownUrl(String fileName) {
String fileSearch = HttpUtil.get(Constant.FILE_SEARCH + "&access_token=" + Constant.ATOKEN + "&key=" + fileName);
String fileSearch = HttpUtil.get(Constant.FILE_SEARCH + "&access_token=" + Constant.ATOKEN + "&key=" + fileName + "&recursion=1&dir=" + Constant.APP_PATH);
System.out.println("fileSearch:"+fileSearch);
JSONObject jsonObject = new JSONObject(fileSearch);
JSONArray list = jsonObject.getJSONArray("list");
JSONObject listJSONObject = list.getJSONObject(0);
@ -136,15 +133,11 @@ public class FileUtilsBaidu {
*/
private static String create(String fileName, Long size, Integer isDir, String blockList, String uploadid) {
String strURL = Constant.FILE_MANAGER_URL + "?method=create&access_token=" + Constant.ATOKEN;
// String params = "path=" + Constant.APP_PATH + fileName + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir +"&uploadid"+uploadid;
// return open(strURL, params, "POST");
//
// //方式一
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("path", Constant.APP_PATH + fileName);
paramMap.put("size", size);
// paramMap.put("autoinit", 1);
// paramMap.put("rtype", 1);
paramMap.put("autoinit", 1);
paramMap.put("rtype", 2);
String str ="[\"" +blockList +"\"]";
paramMap.put("block_list", str);
paramMap.put("isdir",isDir);
@ -154,7 +147,6 @@ public class FileUtilsBaidu {
System.out.println("block_list :" + paramMap.get("block_list"));
System.out.println("uploadid :" + paramMap.get("uploadid"));
System.out.println("path :" + paramMap.get("path"));
//
return result;
}
@ -183,9 +175,7 @@ public class FileUtilsBaidu {
//方式二
String result = sendFile(url, files[i]);
log.info("正在上传分片文件{}{}", result, i);
// Thread.sleep(3000);
}
return path;
} catch (Exception e) {
e.printStackTrace();

View File

@ -0,0 +1,558 @@
package com.ruoyi.web.test.controller.baiduyunpan;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import lombok.SneakyThrows;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
/**
* @Auther: Wang
* @Date: 2021/07/25 02:02
* 功能描述:
*/
public class FileUtilsBaiduBeack {
private static final Log log = LogFactory.get();
// public static void main(String[] args) {
// //不能有空格
//// String filePath = "D:\\data\\ces\\";
//// String fileName = "day4_MySQL性能优化总结.zip";
// String filePath = "D:\\Wang\\";
// String fileName = "22.txt";
// System.out.println(save(filePath, fileName));
// }
/**
* @Description: TODO 保存文件
* @param: filePath 文件路径
* @param: fileName 文件名称
* return 文件下载地址
*/
@SneakyThrows
private static String save(String filePath, String fileName) {
//本地文件地址
String absoluteFilePath = filePath + fileName;
//云端文件地址
String cloudPath = Constant.APP_PATH + fileName;
//文件分片并获取md5值
File file = new File(absoluteFilePath);
File[] separate = separate(absoluteFilePath, Constant.UNIT);
StringBuffer md5s = new StringBuffer();
if (separate.length == 1) {
md5s.append(getMD5(separate[0]));
// md5s.append(DigestUtils.md5Hex(new FileInputStream(separate[0])));
}
if (separate.length > 1) {
for (int i = 0; i < separate.length; i++) {
md5s.append(getMD5(separate[i]) + "\",\"");
// md5s.append(DigestUtils.md5Hex(new FileInputStream(separate[i])) + "\",\"");
log.info("正在分片,{}{}", separate[i].toString(), i);
}
String s = md5s.toString();
md5s = new StringBuffer(s.substring(0, md5s.length() - 3));
}
Long fileMax = file.length();
//预上传
String precreate = precreate(cloudPath,fileMax, 0, md5s.toString());
log.info("预上传{} iploadid是 {} md5{}", precreate,(String) new JSONObject(precreate).get("uploadid"),md5s.toString());
//分片上传
String upload = upload(cloudPath, (String) new JSONObject(precreate).get("uploadid"), separate);
log.info("分片上传{}", upload);
log.info(" >>>>>>>>>>>>>>>>>>>>>>>>>>");
Thread.sleep(3000);
//创建文件
log.info("创建文件 fileName{} 文件大小{} md5:{} ID:{}", fileName, FileSizeUtil.pathSize(absoluteFilePath),md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
String create = create(fileName, fileMax, 0, md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
log.info("创建文件{}", create);
//获取下载地址
String downUrl = getDownUrl(fileName);
log.info("获取下载地址{}", downUrl);
return downUrl;
}
/**
* @Description: TODO 获取下载地址
* @param: fileName 文件名
*/
private static String getDownUrl(String fileName) {
String fileSearch = HttpUtil.get(Constant.FILE_SEARCH + "&access_token=" + Constant.ATOKEN + "&key=" + fileName + "&recursion=1&dir=" + Constant.APP_PATH);
System.out.println("fileSearch:"+fileSearch);
JSONObject jsonObject = new JSONObject(fileSearch);
JSONArray list = jsonObject.getJSONArray("list");
JSONObject listJSONObject = list.getJSONObject(0);
Long fs_id = listJSONObject.getLong("fs_id");
String url = Constant.DOWN_LOUE_URL + "?method=filemetas&access_token=" + Constant.ATOKEN + "&fsids=[" + fs_id + "]&dlink=1";
String s = HttpUtil.get(url);
JSONObject sJsonObject = new JSONObject(s);
JSONArray jsonArray = sJsonObject.getJSONArray("list");
JSONObject jsonObjectClient = jsonArray.getJSONObject(0);
String dlink = jsonObjectClient.getStr("dlink");
return dlink;
}
/**
* @Description: TODO 创建文件
* @param: fileName 文件名称
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录设置为目录是 size要设置为0
* @param: blockList 文件的md5值 可以把文件分为多个然后分批上传
* @return: java.lang.String
*/
private static String create(String fileName, Long size, Integer isDir, String blockList, String uploadid) {
String strURL = Constant.FILE_MANAGER_URL + "?method=create&access_token=" + Constant.ATOKEN;
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("path", Constant.APP_PATH + fileName);
paramMap.put("size", size);
paramMap.put("autoinit", 1);
paramMap.put("rtype", 2);
String str ="[\"" +blockList +"\"]";
paramMap.put("block_list", str);
paramMap.put("isdir",isDir);
paramMap.put("uploadid",uploadid);
// paramMap.put("app_id",Constant.APP_ID);
String result= HttpUtil.post(strURL, paramMap);
System.out.println("block_list :" + paramMap.get("block_list"));
System.out.println("uploadid :" + paramMap.get("uploadid"));
System.out.println("path :" + paramMap.get("path"));
return result;
}
/**
* @Description: TODO 分片上传
* @param: path 上传到百度网盘的地址
* @param: uploadid 上传的id
* @param: filePath 本地文件的地址
* @return: java.lang.String
*/
private static String upload(String path, String uploadid, File[] files) {
try {
for (int i = 0; i < files.length; i++) {
String url = Constant.SLICING_UPLOAD_FILE_URL + "?method=upload" +
"&access_token=" + Constant.ATOKEN +
"&type=tmpfile&partseq=" + i +
"&path=" + getURLEncoderString(path) +
"&uploadid=" + uploadid;
log.info("files : {} path {}",files[i], path);
//方式一
// HashMap<String, Object> paramMap = new HashMap<>();
// paramMap.put("file", FileUtil.file(files[i]));
// String result= HttpUtil.post(url, paramMap);
//方式二
String result = sendFile(url, files[i]);
log.info("正在上传分片文件{}{}", result, i);
}
return path;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Description: TODO 预上传
* @param: cloudPath 云端路径
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录设置为目录是 size要设置为0
* @param: blockList 文件的md5值 可以把文件分为多个然后分批上传
* @return: java.lang.String
*/
private static String precreate(String cloudPath, Long size, Integer isDir, String blockList) {
String strURL = Constant.GET_READY_FILE_URL + "?method=precreate&access_token=" + Constant.ATOKEN;
String params = "path=" + getURLEncoderString(cloudPath) + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
return open(strURL, params, "POST");
}
/**
* @Description: TODO 获取md5值
* String path 文件地址
*/
private final static String[] strHex = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
private static String getMD5(File path) {
StringBuilder buffer = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b = md.digest(org.apache.commons.io.FileUtils.readFileToByteArray(path));
for (int value : b) {
int d = value;
if (d < 0) {
d += 256;
}
int d1 = d / 16;
int d2 = d % 16;
buffer.append(strHex[d1]).append(strHex[d2]);
}
return buffer.toString();
} catch (Exception e) {
return null;
}
// BigInteger bi = null;
// try {
// byte[] buffer = new byte[8192];
// int len = 0;
// MessageDigest md = MessageDigest.getInstance("MD5");
//
// FileInputStream fis = new FileInputStream(f);
// while ((len = fis.read(buffer)) != -1) {
// md.update(buffer, 0, len);
// }
// fis.close();
// byte[] b = md.digest();
// bi = new BigInteger(1, b);
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return bi.toString(16);
}
/**
* @Description: TODO
* @param: strURL 网址可以是 http://aaa?bbb=1&ccc=2 拼接的
* @param: params 拼接的body参数也就是form表单的参数 ddd=1&eee=2
* @param: method 请求方式 get/post/put/delte等
* @return: java.lang.String
*/
private static String open(String strURL, String params, String method) {
try {
URL url = new URL(strURL);// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(method);
connection.setRequestProperty("Accept", "application/json");// 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/json");// 设置发送数据的格式
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);// utf-8编码
out.append(params);
out.flush();
out.close(); // 读取响应
int length = connection.getContentLength();// 获取长度
InputStream is = connection.getInputStream();
if (length != -1) {
byte[] data = new byte[length];
byte[] temp = new byte[512];
int readLen = 0;
int destPos = 0;
while ((readLen = is.read(temp)) > 0) {
System.arraycopy(temp, 0, data, destPos, readLen);
destPos += readLen;
}
return new String(data, StandardCharsets.UTF_8);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendFile(String url, String param, String file) {
if (url == null || param == null) {
return url;
}
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
//设置链接超时时间为2秒
conn.setConnectTimeout(1000);
//设置读取超时为2秒
conn.setReadTimeout(1000);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
out.write(file);
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println(e.getMessage() + "地址:" + url);
return null;
}
//使用finally块来关闭输出流输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
return null;
}
}
return result;
}
/**
* @param: filePath
* @param: unit 单个文件大小
* @return: 返回文件的目录
*/
private static File[] separate(Object obj, Integer unit) {
try {
InputStream bis = null;//输入流用于读取文件数据
OutputStream bos = null;//输出流用于输出分片文件至磁盘
File file = null;
if (obj instanceof String) {
file = new File((String) obj);
}
if (obj instanceof File) {
file = (File) obj;
}
String filePath = file.getAbsolutePath();
File newFile = new File(filePath.substring(0, filePath.lastIndexOf("\\") + 1));
String directoryPath = newFile.getAbsolutePath();
long splitSize = unit * 1024 * 1024;//单片文件大小,MB
if (file.length() < splitSize) {
log.info("文件小于单个分片大小,无需分片{}", file.length());
return new File[]{file};
}
//分片二
RandomAccessFile in=null;
RandomAccessFile out =null;
long length=file.length();//文件大小
long count=length%splitSize==0?(length/splitSize):(length/splitSize+1);//文件分片数
byte[] bt=new byte[1024];
in=new RandomAccessFile(file, "r");
for (int i = 1; i <= count; i++) {
out = new RandomAccessFile(new File(filePath+"."+i), "rw");//定义一个可读可写且后缀名为.part的二进制分片文件
long begin = (i-1)*splitSize;
long end = i* splitSize;
int len=0;
in.seek(begin);
while (in.getFilePointer()<end&&-1!=(len=in.read(bt))) {
out.write(bt, 0, len);
}
out.close();
}
//分片一
// bis = new BufferedInputStream(new FileInputStream(file));
// long writeByte = 0;//已读取的字节数
// int len = 0;
// byte[] bt = new byte[1024];
// while (-1 != (len = bis.read(bt))) {
// if (writeByte % splitSize == 0) {
// if (bos != null) {
// bos.flush();
// bos.close();
// }
// bos = new BufferedOutputStream(new FileOutputStream(filePath + "." + (writeByte / splitSize + 1) + ".part"));
// }
// writeByte += len;
// bos.write(bt, 0, len);
// }
log.info("文件分片成功!");
//排除被分片的文件
if (newFile.isDirectory()) {
File[] files = newFile.listFiles();
File[] resultFiles = new File[files.length - 1];
int j = 0;
for (int i = 0; i < files.length; i++) {
if (!files[i].equals(file)) {
resultFiles[j] = files[i];
j++;
}
}
return resultFiles;
}
bos.flush();
bos.close();
bis.close();
return new File[0];
} catch (Exception e) {
log.info("文件分片失败!");
e.printStackTrace();
}
return null;
}
//splitNum:要分几片currentDir分片后存放的位置subSize按多大分片
public static File[] nioSpilt(Object object, int splitNum, String currentDir, double subSize) {
try {
File file = null;
if (object instanceof String) {
file = new File((String) object);
}
if (object instanceof String) {
file = (File) object;
}
FileInputStream fis = new FileInputStream(file);
FileChannel inputChannel = fis.getChannel();
FileOutputStream fos;
FileChannel outputChannel;
long splitSize = (long) subSize;
long startPoint = 0;
long endPoint = splitSize;
for (int i = 1; i <= splitNum; i++) {
fos = new FileOutputStream(currentDir + i);
outputChannel = fos.getChannel();
inputChannel.transferTo(startPoint, splitSize, outputChannel);
startPoint += splitSize;
endPoint += splitSize;
outputChannel.close();
fos.close();
}
inputChannel.close();
fis.close();
File newFile = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf("\\") + 1));
if (newFile.isDirectory()) {
return newFile.listFiles();
}
} catch (Exception e) {
e.printStackTrace();
}
return new File[0];
}
/**
* @Description: TODO 发送文件
* @param: url 发送地址
* @param: file 发送文件
* @return: java.lang.String
*/
public static String sendFile(String url, File file) {
try {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setContentType(ContentType.MULTIPART_FORM_DATA);
builder.addBinaryBody("file", file);
String body = "";
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
//设置请求参数
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
//执行请求操作并拿到结果同步阻塞
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
//释放链接
response.close();
return body;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getURLEncoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public static String URLDecoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLDecoder.decode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}

View File

@ -0,0 +1,228 @@
package com.ruoyi.web.test.controller.bookmark;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ZipUtil;
import com.ruoyi.BackupsYunPan;
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.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.web.test.controller.BaseSpringBootTest;
import com.ruoyi.web.test.controller.baiduyunpan.Constant;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Auther: Wang
* @Date: 2021/04/19 21:16
* 功能描述:
*/
public class HtmlTest extends BaseSpringBootTest {
@Autowired
private ISqMenuService iSqMenuService;
@Autowired
private ISqBookmarkService iSqBookmarkService;
@Autowired
private BackupsYunPan backupsYunPan;
@Test
public void ss(){
try {
System.out.println(DateUtil.now());
Thread.sleep(10000);
//共享数据10每一个线程里面-1
MyRunner2 myRunner2=new MyRunner2();
for(int i=0;i<10;i++){
Thread thread2=new Thread(myRunner2);
//不同的线程传入同一个对象达到线程共享的目的
thread2.start();
//无序由操作系统来调度
}
Thread.sleep(1000000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//百度 备份
// backupsYunPan.BaiDuYunBackups("D:\\data\\ces\\","day4_MySQL性能优化总结.zip",Constant.ATOKEN);
}
class MyRunner2 implements Runnable{
@Override
public void run() {
int max=100,min=1;
long randomNum = System.currentTimeMillis();
int ran3 = (int) (randomNum%(max-min)+min);
Long beginTime = new Date().getTime();
String filePath = "D:/demo/" + "user_1/" + ran3+"/bookmark_bacpks/";
String filePathZip = "D:/demo/" + "user_1/"+ran3 + "/bookmark_zip/";
String fileName = "藏趣云_" + DateUtil.format(DateUtil.date(), "yyyy_MM_dd");
try {
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" +
"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n" +
"<TITLE>Bookmarks</TITLE>\n" +
"<H1>Bookmarks 藏趣云</H1>");
sb.append("<DL>\n");
sb.append(exportToHtml(1L));
sb.append("</DL>\n");
File file = new File(filePath + fileName + MimeTypeUtils.HTML);
if (!file.getParentFile().exists()) { //如果文件的目录不存在
file.getParentFile().mkdirs(); //创建目录
}
if (file.exists()) {
//文件存在
}
OutputStream output = new FileOutputStream(file);
//3: 准备好实现内容的输出 将字符串变为字节数组
byte data[] = sb.toString().getBytes();
output.write(data);
output.close();
//打包
ZipUtil.zip(filePath, filePathZip + fileName + MimeTypeUtils.ZIP);
String downUrl = backupsYunPan.BaiDuYunBackups(filePathZip, fileName + MimeTypeUtils.ZIP, Constant.ATOKEN);
//删除目录内文件
FileUtils.deleteFile(filePathZip + fileName + MimeTypeUtils.ZIP);
FileUtils.deleteFile(filePath + fileName + MimeTypeUtils.HTML);
//备份成功了 存数据库
} catch (Exception e) {
logger.error("异常:", e);
}
System.out.println("耗时:"+(new Date().getTime()-beginTime));
}
}
@Test
public void test3() {
Long beginTime = new Date().getTime();
String filePath = "D:/demo/" + "user_1" + "/bookmark_bacpks/";
String filePathZip = "D:/demo/" + "user_1" + "/bookmark_zip/";
String fileName = "藏趣云_" + DateUtil.format(DateUtil.date(), "yyyy_MM_dd");
try {
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" +
"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n" +
"<TITLE>Bookmarks</TITLE>\n" +
"<H1>Bookmarks 藏趣云</H1>");
sb.append("<DL>\n");
sb.append(exportToHtml(1L));
sb.append("</DL>\n");
File file = new File(filePath + fileName + MimeTypeUtils.HTML);
if (!file.getParentFile().exists()) { //如果文件的目录不存在
file.getParentFile().mkdirs(); //创建目录
}
if (file.exists()) {
//文件存在
}
OutputStream output = new FileOutputStream(file);
//3: 准备好实现内容的输出 将字符串变为字节数组
byte data[] = sb.toString().getBytes();
output.write(data);
output.close();
//打包
ZipUtil.zip(filePath, filePathZip + fileName + MimeTypeUtils.ZIP);
String downUrl = backupsYunPan.BaiDuYunBackups(filePathZip, fileName + MimeTypeUtils.ZIP, Constant.ATOKEN);
//删除目录内文件
FileUtils.deleteFile(filePathZip + fileName + MimeTypeUtils.ZIP);
FileUtils.deleteFile(filePath + fileName + MimeTypeUtils.HTML);
//备份成功了 存数据库
} catch (Exception e) {
logger.error("异常:", e);
}
System.out.println("耗时:"+(new Date().getTime()-beginTime));
}
/**
* 导出到html文件
* @param
*/
public StringBuilder exportToHtml(Long userId){
SqMenu sqMenu=new SqMenu();
sqMenu.setUserId(userId);
SqBookmark sqBookmark = new SqBookmark();
sqBookmark.setUserid(userId);
//目录
List<SqMenu> menuList = iSqMenuService.selectSqMenuList(sqMenu);
Map<Long, List<SqMenu>> mapMenu = menuList.stream().collect(Collectors.groupingBy(SqMenu::getParentId));
//书签
List<SqBookmark> bookMarkList = iSqBookmarkService.selectSqBookmarkList(sqBookmark);
Map<Long, List<SqBookmark>> mapBookMark = bookMarkList.stream().collect(Collectors.groupingBy(SqBookmark::getMenuId));
List<SqMenu> sqMenuList = mapMenu.get(0L);
StringBuilder str = new StringBuilder();
str = traverseFile_recursion(sqMenuList,str,mapBookMark,mapMenu);
return str;
}
/**
* @Description:递归书签导出功能
*
* @param * @param sqMenuList
* @param str
* @param mapBookMark
* @param mapMenu
* @return java.lang.StringBuilder
* @Date
* @author: wanghao
*
*/
public StringBuilder traverseFile_recursion (List<SqMenu> sqMenuList,StringBuilder str,Map<Long, List<SqBookmark>> mapBookMark,Map<Long, List<SqMenu>> mapMenu) {
if (sqMenuList != null && !sqMenuList.isEmpty()) {
for (SqMenu f : sqMenuList) {
str.append("<DT><H3 ADD_DATE=\"1584277207\" LAST_MODIFIED=\"0\">").append(f.getMenuName()).append("</H3>\n");
str.append("<DL>\n");
List<SqBookmark> bookmarksList = mapBookMark.get(f.getMenuId());
if (bookmarksList != null && !bookmarksList.isEmpty()) {
for (SqBookmark b : bookmarksList) {
str.append("<DT><A HREF=\""+b.getUrl()+"\" TARGET=\"_blank\">"+b.getTitle()+"</A>\n");
}
}
traverseFile_recursion(mapMenu.get(f.getMenuId()),str,mapBookMark,mapMenu);
str.append("</DL>\n");
}
}
return str;
}
}

View File

@ -6,9 +6,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/dqsj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: root
url: jdbc:mysql://localhost:3306/dqsj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: root
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletRequest;
/**
* 文件处理工具类
*
*
* @author ruoyi
*/
public class FileUtils extends org.apache.commons.io.FileUtils
@ -20,7 +20,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
/**
* 输出指定文件的byte数组
*
*
* @param filePath 文件路径
* @param os 输出流
* @return
@ -76,7 +76,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
/**
* 删除文件
*
*
* @param filePath 文件
* @return
*/
@ -93,9 +93,31 @@ public class FileUtils extends org.apache.commons.io.FileUtils
return flag;
}
/**
* 递归删除目录下的所有文件及子目录下所有文件
* @param dir 将要删除的文件目录
* @return boolean Returns "true" if all deletions were successful.
* If a deletion fails, the method stops attempting to
* delete and returns "false".
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
//递归删除目录中的子目录下
for (int i=0; i<children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空可以删除
return dir.delete();
}
/**
* 文件名称验证
*
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
@ -106,7 +128,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
/**
* 下载文件名重新编码
*
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名

View File

@ -2,11 +2,15 @@ package com.ruoyi.common.utils.file;
/**
* 媒体类型工具类
*
*
* @author ruoyi
*/
public class MimeTypeUtils
{
public static final String HTML = ".html";
public static final String ZIP = ".zip";
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
@ -16,7 +20,7 @@ public class MimeTypeUtils
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" };

View File

@ -1,15 +1,10 @@
package com.ruoyi.common.utils.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.net.*;
import java.security.cert.X509Certificate;
import java.util.Locale;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
@ -22,7 +17,7 @@ import com.ruoyi.common.constant.Constants;
/**
* 通用http发送方法
*
*
* @author ruoyi
*/
public class HttpUtils
@ -259,4 +254,34 @@ public class HttpUtils
return true;
}
}
}
/**
* 格式化路径参数 可选参数
*
* @param uri uri
* @param map map
* @return initUriPathParams
* @throws UnsupportedEncodingException 异常
*/
public static String initUriPathParams(String uri, Map<String, String> map) throws UnsupportedEncodingException {
String key;
String value;
StringBuilder builder = new StringBuilder();
builder.append(uri);
builder.append("?");
for (Map.Entry<String, String> entry : map.entrySet()) {
key = entry.getKey();
value = entry.getValue();
String tmpKv;
tmpKv = String.format(Locale.ROOT, "%s=%s&", URLEncoder.encode(key, "UTF-8"),
URLEncoder.encode(value, "UTF-8"));
builder.append(tmpKv);
}
return builder.toString();
}
}

View File

@ -1,35 +1,35 @@
const { run } = require('runjs')
const chalk = require('chalk')
const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ')
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
const report = rawArgv.includes('--report')
run(`vue-cli-service build ${args}`)
const port = 9526
const publicPath = config.publicPath
var connect = require('connect')
var serveStatic = require('serve-static')
const app = connect()
app.use(
publicPath,
serveStatic('./dist', {
index: ['index.html', '/']
})
)
app.listen(port, function () {
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
if (report) {
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
}
})
} else {
run(`vue-cli-service build ${args}`)
}
const { run } = require('runjs')
const chalk = require('chalk')
const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ')
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
const report = rawArgv.includes('--report')
run(`vue-cli-service build ${args}`)
const port = 9526
const publicPath = config.publicPath
var connect = require('connect')
var serveStatic = require('serve-static')
const app = connect()
app.use(
publicPath,
serveStatic('./dist', {
index: ['index.html', '/']
})
)
app.listen(port, function () {
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
if (report) {
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
}
})
} else {
run(`vue-cli-service build ${args}`)
}

View File

@ -1,64 +1,64 @@
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => {
// 拉取user_info
const roles = res.roles
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
// 测试 默认静态页面
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
.catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
// if (hasPermission(store.getters.roles, to.meta.roles)) {
// next()
// } else {
// next({ path: '/401', replace: true, query: { noGoBack: true }})
// }
// 可删 ↑
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => {
// 拉取user_info
const roles = res.roles
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
// 测试 默认静态页面
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
.catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
// if (hasPermission(store.getters.roles, to.meta.roles)) {
// next()
// } else {
// next({ path: '/401', replace: true, query: { noGoBack: true }})
// }
// 可删 ↑
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})

View File

@ -56,13 +56,32 @@
<el-header height="200px" class="header-below">
<!-- <el-input v-model="input" placeholder="请输入内容"></el-input>-->
<div style="min-width: 500px;margin-top: 80px">
<el-input placeholder="百度一下" v-model="sousou" class="sousoucss notcopy " ref="sousouref">
<img @click="IsCord()" slot="prefix" :src="sousouicon"
style="width: 20px;height: 20px;position: absolute;top: 50%;margin-top: -10px;">
<img @click="IsCord()" slot="prefix" :src="sousouicon"
style="" class="sousou-img">
<input placeholder="百度一下" v-model="sousou" class="search" ref="sousouref">
</input>
<!-- <template slot="prepend">-->
<!-- </template>-->
<!-- -->
<!-- <el-select v-model="select" slot="prepend" placeholder="请选择" style="width: 130px">-->
<!-- <el-option label="餐厅名" value="1"></el-option>-->
<!-- <el-option label="订单号" value="2"></el-option>-->
<!-- <el-option label="用户电话" value="3"></el-option>-->
<!-- </el-select>-->
<!-- <el-button slot="append" icon="el-icon-search"></el-button>-->
<!-- <el-button type="primary" slot="append" icon="el-icon-search" style="width: 80px" @click="getUrl"></el-button>-->
</el-input>
</div>
</el-header>
@ -72,7 +91,7 @@
<el-aside class="mains-left mbl" width="400px">
<div class="label-title">
<div class="title">
<el-dropdown trigger="click" @command="handleCommand">
<el-dropdown trigger="click" @command="handleCommand">
<span class="el-dropdown-link menu-list">
最新收藏<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
@ -209,6 +228,7 @@
} from "@/api/bookmark/bookmark";
export default {
name: 'app',
components: {draggable},
data: function () {
return {
@ -283,17 +303,17 @@
sqTags: [],
sort: 0,
sousuo: '',
type:'',
bkOrderBy:'',
type: '',
bkOrderBy: '',
},
bookmarkList:[],
sortState:true,//,, false true
bookmarkList: [],
sortState: true,//,, false true
}
},
methods: {
goRouter(e){
var flag=e;
goRouter(e) {
var flag = e;
var that = this;
switch (flag) {
case 1:
@ -317,7 +337,7 @@
path: "/content",
query: {
menuId: 'newest',
t:Date.now(),
t: Date.now(),
}
})
}
@ -326,21 +346,21 @@
listByUserAndPolymerization(str) {
console.log(" 最新 星标 回收站 稍后看");
// this.loading = true;
this.queryParams.type=str;
this.queryParams.bkOrderBy="";
this.queryParams.type = str;
this.queryParams.bkOrderBy = "";
listByUserAndPolymerization(this.queryParams).then(response => {
if (response.code == 200) {
//
if (this.sortState){
if (this.sortState) {
this.bookmarkList = this.bookmarkList.concat(response.rows);
}else{
} else {
this.bookmarkList = response.rows;
this.sortState = false;
}
this.total = response.total;
this.listloading = false
this.loading = false;
if (response.total == 0){
if (response.total == 0) {
this.showimg = true;//
}
console.log("请求完毕" + this.queryParams.pageNum)
@ -355,11 +375,11 @@
},
/**切换排序规则**/
handleCommand(command) {
if (this.queryParams.sort != command){
if (this.queryParams.sort != command) {
this.sortState = false;// false true
}
this.queryParams.sort = command;
this.bookmarkList=[]
this.bookmarkList = []
this.listByUserAndPolymerization(command)
},
@ -428,7 +448,7 @@
<style scoped>
.bookmarkUrl {
margin-bottom: 10px;
margin-left: 11px;
margin-left: 10px;
height: 70px;
border-radius: 4px;
line-height: 50px;
@ -699,6 +719,19 @@
<style scoped>
.search{
width: 500px;
height: 45px;
border: 0;
border-radius: 50px;
background: rgba(255, 255, 255, 0.5);
padding-left: 64px ;
}
.search:focus {
outline:none;
}
.main {
/*font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;*/
/*display: flex;*/
@ -719,7 +752,7 @@
/*}*/
/*.sousoucss{*/
/* opacity: 0.6;*/
/* background: rgba(255, 255, 255, 0.5);*/
/*}*/
/*.sousoucss input{*/
/* border:0;*/
@ -732,6 +765,33 @@
/* background-color: #1f2d3d!important;*/
/* opacity: 0.7;*/
/*}*/
.sousoucss >>> .el-select {
background: rgba(255, 255, 255, 0.5) !important;
border: none !important;
}
.sousoucss >>> .el-input--suffix {
background: rgba(255, 255, 255, 0.5) !important;
border: none !important;
}
.sousoucss >>> .el-input__inner {
background: rgba(255, 255, 255, 0.5) !important;
border: none !important;
/*width: 500px !important;*/
/*-moz-border-radius-topright: 50px !important;*/
/*-moz-border-radius-bottomright: 50px !important;*/
/*color: #666c74 !important;*/
/*font-size: 16px !important;*/
/*height: 40px !important;*/
}
.sousou-img {
width: 30px;
height: 30px;
position: relative;
border-radius:50%;
top: 10px;
left: 45px;
}
.choice {
@ -833,7 +893,8 @@
::-webkit-scrollbar-track {
width: 6px;
/*background-color: #fff;*/
background: rgba(255, 255, 255, 0.2);
/*滚动条的背景颜色*/
/*background: rgba(255, 255, 255, 0.2);*/
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;

View File

@ -3,6 +3,7 @@ package com.ruoyi.bookmark.service;
import java.util.List;
import com.ruoyi.bookmark.domain.SqBookmark;
import com.ruoyi.bookmark.pojo.SqBookmarkReq;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.bookmarkhtml.HtmlName;
/**
@ -179,4 +180,11 @@ public interface ISqBookmarkService
*
*/
List<SqBookmark> getlistByTag(SqBookmarkReq sqBookmarkReq);
/**
* 根据URL 删除书签
* @param
*
*/
AjaxResult deleteByUrl(Long userId, String url);
}

View File

@ -22,6 +22,7 @@ import com.ruoyi.bookmark.mapper.SqTagMapper;
import com.ruoyi.bookmark.pojo.SqBookmarkReq;
import com.ruoyi.bookmark.service.ISqTagService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bookmarkhtml.Const;
import com.ruoyi.common.utils.bookmarkhtml.HtmlName;
@ -544,5 +545,23 @@ public class SqBookmarkServiceImpl implements ISqBookmarkService
return sqBookmarkMapper.getlistByTag(sqBookmarkReq);
}
@Override
public AjaxResult deleteByUrl(Long userId, String url) {
//1.根据URL查询书签 会有多条
//2.移动到回收站
//3.修改多个书签目录的数量
// //给原目录 -1
// sqMenuMapper.updateCountReduce(new Long[]{sqBookmark.getMenuId()},1);
return AjaxResult.success("success");
}
}

View File

@ -21,6 +21,10 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,27 @@
package com.ruoyi;
import org.springframework.stereotype.Service;
/**
* @Auther: Wang
* @Date: 2021/11/20 00:19
* 功能描述:
*/
public interface BackupsYunPan {
/**
* @Description:
*
* @param filePath 文件路徑
* @param fileName 文件名称
* @param atoken acc token
* @return
* @Date
* @author: wanghao
*
*/
public String BaiDuYunBackups(String filePath,String fileName ,String atoken);
}

View File

@ -0,0 +1,19 @@
package com.ruoyi;
import com.ruoyi.baiduyunpan.utils.FileUtilsBaidu;
import org.springframework.stereotype.Service;
/**
* @Auther: Wang
* @Date: 2021/11/20 00:19
* 功能描述:
*/
@Service
public class BackupsYunPanImpl implements BackupsYunPan{
@Override
public String BaiDuYunBackups(String filePath, String fileName, String token) {
return FileUtilsBaidu.save(filePath, fileName,token);
}
}

View File

@ -1,7 +1,7 @@
package com.ruoyi.baidu.servise.impl;
package com.ruoyi.baiduyunpan.servise.impl;
import cn.hutool.http.HttpUtil;
import com.ruoyi.baidu.servise.BaiduWangPanServise;
import com.ruoyi.baiduyunpan.servise.BaiduWangPanServise;
import com.ruoyi.common.constant.BaiduUrl;
import org.springframework.stereotype.Service;

View File

@ -1,9 +1,12 @@
package com.ruoyi.web.test.controller;
package com.ruoyi.baiduyunpan.utils;
/**
* @Auther: Wang
* @Date: 2021/07/25 02:03
* 功能描述:
*
* 文档API https://www.wenjiangs.com/doc/leikdy8r
*
*/
public interface Constant {
String APP_ID="24066444";
@ -13,15 +16,14 @@ public interface Constant {
String SING_key="dBpomXW%duC2L8l6MW3yTpaXhX=-8oj0";
String APP_PATH="/apps/"+APP_NAME+"/";
// https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&redirect_uri=https://www.baidu.com/&scope=basic,netdisk&display=tv&qrcode=1&force_login=1
// https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=0a291eb3fd3ed6ccc74cc46bc5540191&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&client_secret=RfvvGbkN95CuXlaoZVzzsvGiz9Her6qq&redirect_uri=oob
//https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&redirect_uri=https://www.baidu.com/&scope=basic,netdisk&display=tv&qrcode=1&force_login=1
//https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=0a291eb3fd3ed6ccc74cc46bc5540191&client_id=7NpRdcorSxoqxIKAkzLXuOhVr8NQekA9&client_secret=RfvvGbkN95CuXlaoZVzzsvGiz9Her6qq&redirect_uri=oob
//单位mb
// 普通用户单个分片大小固定为4MB文件大小如果小于4MB无需切片直接上传即可单文件总大小上限为4G
//普通会员用户单个分片大小上限为16MB单文件总大小上限为10G
//超级会员用户单个分片大小上限为32MB单文件总大小上限为20G
Integer UNIT=4;
//获取授权码需要扫码登陆
String GET_CODE_URL="https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id="+APP_KEY+"&redirect_uri=oob&scope=basic,netdisk&display=tv&qrcode=1&force_login=1";
@ -31,13 +33,15 @@ public interface Constant {
//根据授权码换取token
String GET_TOKEN_BY_CODE="https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code="+CODE+"&client_id="+APP_KEY+"&client_secret="+SECRET_KEY+"&redirect_uri=oob";
//"refresh_token": "122.035106ef57234db73fa1d6077df6b2a4.YD6wvL7Qcuh-Jsz3KUYhob9bYABdvCAAwf6pX3e.9r3fbA",
//"access_token": "121.1bbdb55745ea8eebdc6fe83f0481c676.YsAIaraM0JxC1aw_DEbopy8wLGK7mdg6mTGeR8Y.6nzOlA",
//获取到的TOKEN
String RTOKEN="122.fec5f9d6dd1644c2c57c89cc510f7ec8.YBMpVZwjo9y5kSMFnVmSMJL9dj25T5X02gjLwV8.1J2sEw";
String ATOKEN="121.d8ab3687bd67e9b245b6a10f7af7afc3.YCQGBie5JO6U7nCl-ZLVC3pX-sTUFIgnV6hH1Rw.3zI4rQ";
String ATOKEN="121.1bbdb55745ea8eebdc6fe83f0481c676.YsAIaraM0JxC1aw_DEbopy8wLGK7mdg6mTGeR8Y.6nzOlA";
//操作文件 copy, mover, rename, delete
String FILE_MANAGER_URL=" https://pan.baidu.com/rest/2.0/xpan/file";
//操作文件 method = copy, mover, rename, delete
String FILE_MANAGER_URL="https://pan.baidu.com/rest/2.0/xpan/file";
//预上传
String GET_READY_FILE_URL="https://pan.baidu.com/rest/2.0/xpan/file";
@ -51,5 +55,4 @@ public interface Constant {
//文件搜索
String FILE_SEARCH="https://pan.baidu.com/rest/2.0/xpan/file?method=search";
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.web.test.controller;
package com.ruoyi.baiduyunpan.utils;
import java.io.File;
import java.io.FileInputStream;

View File

@ -0,0 +1,569 @@
package com.ruoyi.baiduyunpan.utils;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.ruoyi.baiduyunpan.utils.Constant;
import com.ruoyi.baiduyunpan.utils.FileSizeUtil;
import lombok.SneakyThrows;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
/**
* @Auther: Wang
* @Date: 2021/07/25 02:02
* 功能描述:
*/
public class FileUtilsBaidu {
private static final Log log = LogFactory.get();
// public static void main(String[] args) {
// //不能有空格
//// String filePath = "D:\\data\\ces\\";
//// String fileName = "day4_MySQL性能优化总结.zip";
// String filePath = "D:\\Wang\\";
// String fileName = "22.txt";
// System.out.println(save(filePath, fileName));
// }
/**
* @Description: TODO 保存文件
* @param: filePath 文件路径
* @param: fileName 文件名称
* return 文件下载地址
*/
@SneakyThrows
public static String save(String filePath, String fileName, String token) {
//本地文件地址
String absoluteFilePath = filePath + fileName;
//云端文件地址
String cloudPath = Constant.APP_PATH + fileName;
//文件分片并获取md5值
File file = new File(absoluteFilePath);
File[] separate = separate(absoluteFilePath, Constant.UNIT);
StringBuffer md5s = new StringBuffer();
if (separate.length == 1) {
md5s.append(getMD5(separate[0]));
// md5s.append(DigestUtils.md5Hex(new FileInputStream(separate[0])));
}
if (separate.length > 1) {
for (int i = 0; i < separate.length; i++) {
md5s.append(getMD5(separate[i]) + "\",\"");
// md5s.append(DigestUtils.md5Hex(new FileInputStream(separate[i])) + "\",\"");
log.info("正在分片,{}{}", separate[i].toString(), i);
}
String s = md5s.toString();
md5s = new StringBuffer(s.substring(0, md5s.length() - 3));
}
Long fileMax = file.length();
//预上传
String precreate = precreate(cloudPath,fileMax, 0, md5s.toString(),token);
log.info("预上传{} iploadid是 {} md5{}", precreate,(String) new JSONObject(precreate).get("uploadid"),md5s.toString());
//分片上传
String upload = upload(cloudPath, (String) new JSONObject(precreate).get("uploadid"), separate,token);
log.info("分片上传{}", upload);
log.info(" >>>>>>>>>>>>>>>>>>>>>>>>>>");
Thread.sleep(3000);
//创建文件
log.info("创建文件 fileName{} 文件大小{} md5:{} ID:{}", fileName, FileSizeUtil.pathSize(absoluteFilePath),md5s.toString(),(String) new JSONObject(precreate).get("uploadid"));
String create = create(fileName, fileMax, 0, md5s.toString(),(String) new JSONObject(precreate).get("uploadid"),token);
log.info("创建文件{}", create);
//获取下载地址
String downUrl = getDownUrl(fileName,token);
log.info("获取下载地址{}", downUrl);
return downUrl;
}
/**
* @Description: TODO 获取下载地址
* @param: fileName 文件名
* @param: token token
*/
private static String getDownUrl(String fileName,String token) {
String fileSearch = HttpUtil.get(Constant.FILE_SEARCH + "&access_token=" + token + "&key=" + fileName + "&recursion=1&dir=" + Constant.APP_PATH);
System.out.println("fileSearch:"+fileSearch);
JSONObject jsonObject = new JSONObject(fileSearch);
JSONArray list = jsonObject.getJSONArray("list");
JSONObject listJSONObject = list.getJSONObject(0);
Long fs_id = listJSONObject.getLong("fs_id");
String url = Constant.DOWN_LOUE_URL + "?method=filemetas&access_token=" + token + "&fsids=[" + fs_id + "]&dlink=1";
String s = HttpUtil.get(url);
JSONObject sJsonObject = new JSONObject(s);
JSONArray jsonArray = sJsonObject.getJSONArray("list");
JSONObject jsonObjectClient = jsonArray.getJSONObject(0);
String dlink = jsonObjectClient.getStr("dlink");
return dlink;
}
/**
* @Description: TODO 创建文件
* @param: fileName 文件名称
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录设置为目录是 size要设置为0
* @param: blockList 文件的md5值 可以把文件分为多个然后分批上传
* @param: token token
* @return: java.lang.String
*/
private static String create(String fileName, Long size, Integer isDir, String blockList, String uploadid,String token) {
String strURL = Constant.FILE_MANAGER_URL + "?method=create&access_token=" + token;
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("path", Constant.APP_PATH + fileName);
paramMap.put("size", size);
paramMap.put("autoinit", 1);
// 文件命名策略默认0
// 0 为不重命名返回冲突
// 1 为只要path冲突即重命名
// 2 为path冲突且block_list不同才重命名
// 3 为覆盖
paramMap.put("rtype", 1);
String str ="[\"" +blockList +"\"]";
paramMap.put("block_list", str);
paramMap.put("isdir",isDir);
paramMap.put("uploadid",uploadid);
// paramMap.put("app_id",Constant.APP_ID);
String result= HttpUtil.post(strURL, paramMap);
System.out.println("block_list :" + paramMap.get("block_list"));
System.out.println("uploadid :" + paramMap.get("uploadid"));
System.out.println("path :" + paramMap.get("path"));
return result;
}
/**
* @Description: TODO 分片上传
* @param: path 上传到百度网盘的地址
* @param: uploadid 上传的id
* @param: filePath 本地文件的地址
* @param: token token
* @return: java.lang.String
*/
private static String upload(String path, String uploadid, File[] files,String token) {
try {
for (int i = 0; i < files.length; i++) {
String url = Constant.SLICING_UPLOAD_FILE_URL + "?method=upload" +
"&access_token=" + token +
"&type=tmpfile&partseq=" + i +
"&path=" + getURLEncoderString(path) +
"&uploadid=" + uploadid;
log.info("files : {} path {}",files[i], path);
//方式一
// HashMap<String, Object> paramMap = new HashMap<>();
// paramMap.put("file", FileUtil.file(files[i]));
// String result= HttpUtil.post(url, paramMap);
//方式二
String result = sendFile(url, files[i]);
log.info("正在上传分片文件{}{}", result, i);
}
return path;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Description: TODO 预上传
* @param: cloudPath 云端路径
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录设置为目录是 size要设置为0
* @param: blockList 文件的md5值 可以把文件分为多个然后分批上传
* @param: token acc token
* @return: java.lang.String
*/
private static String precreate(String cloudPath, Long size, Integer isDir, String blockList,String token) {
String strURL = Constant.GET_READY_FILE_URL + "?method=precreate&access_token=" + token;
String params = "path=" + getURLEncoderString(cloudPath) + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
return open(strURL, params, "POST");
}
/**
* @Description: TODO 获取md5值
* String path 文件地址
*/
private final static String[] strHex = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
private static String getMD5(File path) {
StringBuilder buffer = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b = md.digest(org.apache.commons.io.FileUtils.readFileToByteArray(path));
for (int value : b) {
int d = value;
if (d < 0) {
d += 256;
}
int d1 = d / 16;
int d2 = d % 16;
buffer.append(strHex[d1]).append(strHex[d2]);
}
return buffer.toString();
} catch (Exception e) {
return null;
}
// BigInteger bi = null;
// try {
// byte[] buffer = new byte[8192];
// int len = 0;
// MessageDigest md = MessageDigest.getInstance("MD5");
//
// FileInputStream fis = new FileInputStream(f);
// while ((len = fis.read(buffer)) != -1) {
// md.update(buffer, 0, len);
// }
// fis.close();
// byte[] b = md.digest();
// bi = new BigInteger(1, b);
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return bi.toString(16);
}
/**
* @Description: TODO
* @param: strURL 网址可以是 http://aaa?bbb=1&ccc=2 拼接的
* @param: params 拼接的body参数也就是form表单的参数 ddd=1&eee=2
* @param: method 请求方式 get/post/put/delte等
* @return: java.lang.String
*/
private static String open(String strURL, String params, String method) {
try {
URL url = new URL(strURL);// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(method);
connection.setRequestProperty("Accept", "application/json");// 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/json");// 设置发送数据的格式
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);// utf-8编码
out.append(params);
out.flush();
out.close(); // 读取响应
int length = connection.getContentLength();// 获取长度
InputStream is = connection.getInputStream();
if (length != -1) {
byte[] data = new byte[length];
byte[] temp = new byte[512];
int readLen = 0;
int destPos = 0;
while ((readLen = is.read(temp)) > 0) {
System.arraycopy(temp, 0, data, destPos, readLen);
destPos += readLen;
}
return new String(data, StandardCharsets.UTF_8);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendFile(String url, String param, String file) {
if (url == null || param == null) {
return url;
}
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
//设置链接超时时间为2秒
conn.setConnectTimeout(1000);
//设置读取超时为2秒
conn.setReadTimeout(1000);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
out.write(file);
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println(e.getMessage() + "地址:" + url);
return null;
}
//使用finally块来关闭输出流输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
return null;
}
}
return result;
}
/**
* @param: filePath
* @param: unit 单个文件大小
* @return: 返回文件的目录
*/
private static File[] separate(Object obj, Integer unit) {
try {
InputStream bis = null;//输入流用于读取文件数据
OutputStream bos = null;//输出流用于输出分片文件至磁盘
File file = null;
if (obj instanceof String) {
file = new File((String) obj);
}
if (obj instanceof File) {
file = (File) obj;
}
String filePath = file.getAbsolutePath();
File newFile = new File(filePath.substring(0, filePath.lastIndexOf("\\") + 1));
String directoryPath = newFile.getAbsolutePath();
long splitSize = unit * 1024 * 1024;//单片文件大小,MB
if (file.length() < splitSize) {
log.info("文件小于单个分片大小,无需分片{}", file.length());
return new File[]{file};
}
//分片二
RandomAccessFile in=null;
RandomAccessFile out =null;
long length=file.length();//文件大小
long count=length%splitSize==0?(length/splitSize):(length/splitSize+1);//文件分片数
byte[] bt=new byte[1024];
in=new RandomAccessFile(file, "r");
for (int i = 1; i <= count; i++) {
out = new RandomAccessFile(new File(filePath+"."+i), "rw");//定义一个可读可写且后缀名为.part的二进制分片文件
long begin = (i-1)*splitSize;
long end = i* splitSize;
int len=0;
in.seek(begin);
while (in.getFilePointer()<end&&-1!=(len=in.read(bt))) {
out.write(bt, 0, len);
}
out.close();
}
//分片一
// bis = new BufferedInputStream(new FileInputStream(file));
// long writeByte = 0;//已读取的字节数
// int len = 0;
// byte[] bt = new byte[1024];
// while (-1 != (len = bis.read(bt))) {
// if (writeByte % splitSize == 0) {
// if (bos != null) {
// bos.flush();
// bos.close();
// }
// bos = new BufferedOutputStream(new FileOutputStream(filePath + "." + (writeByte / splitSize + 1) + ".part"));
// }
// writeByte += len;
// bos.write(bt, 0, len);
// }
log.info("文件分片成功!");
//排除被分片的文件
if (newFile.isDirectory()) {
File[] files = newFile.listFiles();
File[] resultFiles = new File[files.length - 1];
int j = 0;
for (int i = 0; i < files.length; i++) {
if (!files[i].equals(file)) {
resultFiles[j] = files[i];
j++;
}
}
return resultFiles;
}
bos.flush();
bos.close();
bis.close();
return new File[0];
} catch (Exception e) {
log.info("文件分片失败!");
e.printStackTrace();
}
return null;
}
//splitNum:要分几片currentDir分片后存放的位置subSize按多大分片
public static File[] nioSpilt(Object object, int splitNum, String currentDir, double subSize) {
try {
File file = null;
if (object instanceof String) {
file = new File((String) object);
}
if (object instanceof String) {
file = (File) object;
}
FileInputStream fis = new FileInputStream(file);
FileChannel inputChannel = fis.getChannel();
FileOutputStream fos;
FileChannel outputChannel;
long splitSize = (long) subSize;
long startPoint = 0;
long endPoint = splitSize;
for (int i = 1; i <= splitNum; i++) {
fos = new FileOutputStream(currentDir + i);
outputChannel = fos.getChannel();
inputChannel.transferTo(startPoint, splitSize, outputChannel);
startPoint += splitSize;
endPoint += splitSize;
outputChannel.close();
fos.close();
}
inputChannel.close();
fis.close();
File newFile = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf("\\") + 1));
if (newFile.isDirectory()) {
return newFile.listFiles();
}
} catch (Exception e) {
e.printStackTrace();
}
return new File[0];
}
/**
* @Description: TODO 发送文件
* @param: url 发送地址
* @param: file 发送文件
* @return: java.lang.String
*/
public static String sendFile(String url, File file) {
try {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setContentType(ContentType.MULTIPART_FORM_DATA);
builder.addBinaryBody("file", file);
String body = "";
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
//设置请求参数
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
//执行请求操作并拿到结果同步阻塞
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
//释放链接
response.close();
return body;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getURLEncoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public static String URLDecoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLDecoder.decode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}