Java百度网盘上传图片(文件)
文章目录
Java百度网盘上传图片(文件)前言一、准备工作1.成为百度网盘的开发者2.获取token3.手动获取token4.定时任务进行刷新refreshtoken换取得到新的token5.需要准备的工具类二、上传1.上传的三个接口2.调用接口总结前言
项目中有一个服务器调用百度网盘的接口实现服务器定时上传图片。
Ps:是百度网盘!不是百度云!
不知道会有人看吗,能看明白我写的吗。
一、准备工作
1.成为百度网盘的开发者
百度网盘开发者平台.
2.获取token
1.配置回调地址,获取code,
百度开发者中心.这里是用来配置回调地址的。
点击工程名,安全设置。就可以配置回调地址了。回调地址应该是一个服务器域名。得到code,用code换token。不过,我的回调地址是后台的,就无法访问。所以我是手动获取的。
3.手动获取token
因为我的回调地址域名是后台服务器。就无法直接访问。所以我手动获取token。(我猜是这样子的,其实为啥访问不了我的回调地址我也不知道。)
手动获取token上面的步骤都需要做的。唯一改变的就是回调地址换成百度网盘默认的oob就可以了。
链接: 获取token的说明.
我们用第一种方式就可以了。
在浏览器中输入如上参数,只需要将最后的回调URL改成oob即可。如果有错要注意一下你的参数,url是否正确。
用得到的code和你的注册时的参数。用浏览器访问这个地址就可以了。注意文档中说的API KEY其实就是你的APPKEY.这样你就会得到你需要的access_token和refresh_token了。
我是拿到后就放到ruoyi的参数配置中直接用了。ruoyi是存在redis和数据库中了。
4.定时任务进行刷新refreshtoken换取得到新的token
//通过refreshToken获得新的tokenpublic void getNewToken(){System.out.println("执行获取token的方法");//百度网盘tokenString refreshToken = configService.selectConfigByKey("baidu.upload.wpRefreshToken");String apiKey = configService.selectConfigByKey("baidu.upload.apiKey");String secretKey = configService.selectConfigByKey("baidu.upload.secretKey");String url = "/oauth/2.0/token?grant_type=refresh_token"+"&refresh_token="+refreshToken+"&client_id="+apiKey+"&client_secret="+secretKey;String newToken = HttpUtil.get(url);JSONObject jsonObject = JSON.parseObject(newToken);String access_token = jsonObject.getString("access_token");String refresh_token = jsonObject.getString("refresh_token");System.out.println(access_token);System.out.println(refresh_token);//修改数据库和redis中token,refreshtoken的值SysConfig sysConfig = new SysConfig();sysConfig.setConfigId(103L);sysConfig.setConfigKey("baidu.upload.wpToken");sysConfig.setConfigValue(access_token);configService.updateConfig(sysConfig);sysConfig.setConfigId(104L);sysConfig.setConfigKey("baidu.upload.wpRefreshToken");sysConfig.setConfigValue(refresh_token);configService.updateConfig(sysConfig);return;}
5.需要准备的工具类
pom中引入hutoo工具类
<!--工具类--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.9</version></dependency>
转md5json串
例子: //转MD5的json//files是文件地址String md5One = getMD5One(files);JSONArray jsonArray = new JSONArray();jsonArray.add(md5One);readyUpload.setBlock_list(jsonArray.toJSONString());private final static String[] strHex = {"0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};public static String getMD5One(String path) {StringBuffer sb = new StringBuffer();try {MessageDigest md = MessageDigest.getInstance("MD5");byte[] b = md.digest(FileUtils.readFileToByteArray(new File(path)));for (int i = 0; i < b.length; i++) {int d = b[i];if (d < 0) {d += 256;}int d1 = d / 16;int d2 = d % 16;sb.append(strHex[d1] + strHex[d2]);}} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return sb.toString();}
根据地址计算图片大小
/*** @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);}
第一个接口所需要的的实体类
import lombok.Data;@Datapublic class ReadyUpload {// 上传后使用的文件绝对路径,需要urlencode(必选)private String path;//文件或目录的大小,单位B,目录的话大小为0(必选)private String size;//是否目录,0 文件、1 目录(必选)private String isdir;// 固定值1(不必选)private int autoinit;//文件命名策略,默认0//0 为不重命名,返回冲突//1 为只要path冲突即重命名//2 为path冲突且block_list不同才重命名//3 为覆盖//(不必须按)private int rtype;//上传idprivate String uploadid;//文件各分片MD5数组的json串private String block_list;private String content_md5;private String slice_md5;private String local_ctime;private String local_mtime;}
第三个接口需要的实体类
import lombok.Data;@Datapublic class FolderMerge {//上传后使用的文件绝对路径(必填)private String path;//文件或目录的大小,必须要和文件真实大小保持一致(必填)private String size;//是否目录,0 文件、1 目录(必填)private String isdir;private String blockList;}
二、上传
链接: 上传说明文档.
看着说明文档就可以了。比较坑的一点就是上传的第二步骤,我用的官方文档的地址没有成功,会报没有用户不存在的错误。在网上找了好久,接口中换了下参数。
链接: 参考一下这个.
或者直接看我代码第二步中的接口就可以了。那就直接上代码了。
1.上传的三个接口
代码如下(示例):
/*** 预上传* @param readyUpload 预上传参数* @return 响应参数*/public String readyUpload(ReadyUpload readyUpload) {// 请求url//百度网盘tokenString accessToken = configService.selectConfigByKey("baidu.upload.wpToken");String url = "/rest/2.0/xpan/file?method=precreate"+"&access_token="+accessToken;try {Map<String, Object> map = new HashMap<>();map.put("path",readyUpload.getPath());map.put("size",readyUpload.getSize());map.put("isdir",readyUpload.getIsdir());map.put("autoinit",readyUpload.getAutoinit());map.put("block_list",readyUpload.getBlock_list());map.put("rtype",3);//String param = GsonUtils.toJson(map);//发送请求//String result = HttpUtil.post(url, accessToken,"application/json", param);String result = cn.hutool.http.HttpUtil.post(url, map);System.out.println(result);return result;}catch (Exception e){e.printStackTrace();}return null;}
注意分片上传的接口参数和官网有出入。
/*** 分片上传* @param file 上传的文件内容* @param path 上传后使用的文件绝对路径,需要urlencode*** @param uploadid precreate接口下发的uploadid* @param partseq 文件分片的位置序号,从0开始,参考precreate接口返回的block_list* @return*/public String slicingUpload(String file, String path, String uploadid, int partseq) throws Exception {//百度网盘tokenString accessToken = configService.selectConfigByKey("baidu.upload.wpToken");//百度网盘appIdString appId = configService.selectConfigByKey("baidu.upload.appId");//token// 请求urlString url = "https://d./rest/2.0/pcs/superfile2?"+"&app_id="+appId+"&access_token="+accessToken+"&method=upload&type=tmpfile"+"&path="+path+"&uploadid="+uploadid+"&partseq="+partseq;Map<String, Object> map = new HashMap<>();map.put("file",new File(file));try {String result = HttpUtil.post(url, map);System.out.println(result);return result;}catch (Exception e){e.printStackTrace();}return null;}
第三步,创建文件
/*** 创建文件 用于将多个分片合并成一个文件,完成文件的上传。* 备注:可以使用该接口创建文件夹。* @param folderMerge 创建文件参数* @return*/public String folderMerge(FolderMerge folderMerge) {//百度网盘tokenString accessToken = configService.selectConfigByKey("baidu.upload.wpToken");// 请求urlString url = "/rest/2.0/xpan/file?method=create"+"&access_token=" + accessToken;try {Map<String, Object> map = new HashMap<>();//todomap.put("path",folderMerge.getPath());map.put("size",folderMerge.getSize());map.put("isdir",folderMerge.getIsdir());map.put("block_list",folderMerge.getBlockList());String result = HttpUtil.post(url,map);System.out.println(result);return result;}catch (Exception e){e.printStackTrace();}return null;}
post请求好像都可以用huttool的工具类发送(和代码无关,给我自己看的)
/*** 发送post请求** @param urlString 网址* @param paramMap post表单数据* @return 返回数据*/public static String post(String urlString, Map<String, Object> paramMap) {return post(urlString, paramMap, HttpGlobalConfig.timeout);}
2.调用接口
代码如下(示例):
@RestController@Slf4j@Component("wpUploadController")public class WpUploadController {@Value("${ruoyi.profile}")private String profile;/*** 上传接口测试** @return* @throws Exception*/@PostMapping("/gototest")public void Test() throws Exception {try {//文件地址String files = "D:\\zz.jpg";readyUpload.setIsdir("0");readyUpload.setAutoinit(1);readyUpload.setSize(pathSize(files));System.out.println(pathSize(files));//转MD5的jsonString md5One = getMD5One(files);JSONArray jsonArray = new JSONArray();jsonArray.add(md5One);readyUpload.setBlock_list(jsonArray.toJSONString());String result = uploadServce.readyUpload(readyUpload);JSONObject jsonObject = JSON.parseObject(result);String uploadid = jsonObject.getString("uploadid");String block_list = jsonObject.getString("block_list");String path = jsonObject.getString("path");System.out.println(path);//分片上传String slicingUploadresult = uploadServce.slicingUpload(files, path, uploadid, 0);JSONObject slicingUploadObject = JSON.parseObject(slicingUploadresult);String md5 = slicingUploadObject.getString("md5");// //创建文件直接上传FolderMerge folderMerge = new FolderMerge();folderMerge.setPath(path);// folderMerge.setSize("702");folderMerge.setSize(pathSize(files));folderMerge.setIsdir("0");JSONArray jsonArray2 = new JSONArray();jsonArray2.add(md5);folderMerge.setBlockList(jsonArray2.toJSONString());String folderMergeResult = uploadServce.folderMerge(folderMerge);}} catch (Exception e) {System.out.println("网盘上传图片失败!");e.printStackTrace();}}private final static String[] strHex = {"0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};public static String getMD5One(String path) {StringBuffer sb = new StringBuffer();try {MessageDigest md = MessageDigest.getInstance("MD5");byte[] b = md.digest(FileUtils.readFileToByteArray(new File(path)));for (int i = 0; i < b.length; i++) {int d = b[i];if (d < 0) {d += 256;}int d1 = d / 16;int d2 = d % 16;sb.append(strHex[d1] + strHex[d2]);}} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return sb.toString();}/*** @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);}}
该处使用的url网络请求的数据。
总结
post请求好像都可以用huttool的工具类发送,
顺便给大家分享一下stream流的文章。
链接: java8Stream流常用操作.