Java百度网盘上传图片(文件)
文章目录
前言
项目中有一个服务器调用百度网盘的接口实现服务器定时上传图片。
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获得新的token
public void getNewToken(){
System.out.println("执行获取token的方法");
//百度网盘token
String refreshToken = configService.selectConfigByKey("baidu.upload.wpRefreshToken");
String apiKey = configService.selectConfigByKey("baidu.upload.apiKey");
String secretKey = configService.selectConfigByKey("baidu.upload.secretKey");
String url = "https://openapi.baidu.com/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;
@Data
public 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;
//上传id
private 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;
@Data
public 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
//百度网盘token
String accessToken = configService.selectConfigByKey("baidu.upload.wpToken");
String url = "http://pan.baidu.com/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 {
//百度网盘token
String accessToken = configService.selectConfigByKey("baidu.upload.wpToken");
//百度网盘appId
String appId = configService.selectConfigByKey("baidu.upload.appId");
//token
// 请求url
String url = "https://d.pcs.baidu.com/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) {
//百度网盘token
String accessToken = configService.selectConfigByKey("baidu.upload.wpToken");
// 请求url
String url = "https://pan.baidu.com/rest/2.0/xpan/file?method=create"+"&access_token=" + accessToken;
try {
Map<String, Object> map = new HashMap<>();
//todo
map.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的json
String 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流常用操作.