概述
JAVA实现百度网盘文件上传
配置信息的获取可以看专栏中的其他博客
一、常量配置
package com.shp.dev.service.baidu;
/**
* @Description: TODO 百度网盘基本常量信息
*/
public interface Constant {
String APP_ID="24110959";
String APP_NAME="云存储";
String APP_KEY="cVQ2xjHGyzsIzq3kxKXK5dEzclBDGrxG";
String SECRET_KEY="DaZzd20bxXf9PPNOArPEpICsxc4yMgpf";
String SING_key="aA4nWN4oMyRpJ6^N%1K7X0jmeFfUhlkq";
String APP_PATH="/apps/"+APP_NAME+"/";
//单位mb
// 普通用户单个分片大小固定为4MB(文件大小如果小于4MB,无需切片,直接上传即可),单文件总大小上限为4G。
//普通会员用户单个分片大小上限为16MB,单文件总大小上限为10G。
//超级会员用户单个分片大小上限为32MB,单文件总大小上限为20G。
Integer UNIT=32;
//获取授权码,需要扫码登陆
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="389853bcabdb033c1bcf3e6b5a6dba61";
//根据授权码换取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";
//获取到的TOKEN
String RTOKEN="122.fec5f9d6dd1644c2c57c89cc510f7ec8.YBMpVZwjo9y5kSMFnVmSMJL9dj25T5X02gjLwV8.1J2sEw";
String ATOKEN="121.03680b5ab4a5fe8dba360b09f161595e.Yga1poFnDVL6-w3_cDt3xtJtMUKbHuoCaO3CmYO.TxDw4Q";
//操作文件 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";
}
二、文件上传工具
package com.shp.dev.service.baidu;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
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 static com.shp.dev.service.baidu.Constant.*;
/**
* @Description: TODO 上传文件到百度网盘
*/
@Slf4j
public class FileUtils {
@SneakyThrows
public static void main(String[] args) {
//不能有空格
String filePath = "C:\Users\Administrator\Desktop\分片\";
String fileName = "a.jpg";
System.out.println(save(filePath, fileName));
}
/**
* @Description: TODO 保存文件
* @param: filePath 文件路径
* @param: fileName 文件名称
* return 文件下载地址
*/
private static String save(String filePath, String fileName) {
//本地文件地址
String absoluteFilePath = filePath + fileName;
//云端文件地址
String cloudPath = APP_PATH + fileName;
//文件分片并获取md5值
File file = new File(absoluteFilePath);
File[] separate = separate(absoluteFilePath, UNIT);
StringBuffer md5s = new StringBuffer();
if (separate.length == 1) {
md5s.append(getMD5(separate[0]));
}
if (separate.length > 1) {
for (int i = 0; i < separate.length; i++) {
md5s.append(getMD5(separate[i]) + "","");
log.info("正在分片,{}{}", separate[i].toString(), i);
}
String s = md5s.toString();
md5s = new StringBuffer(s.substring(0, md5s.length() - 3));
}
//预上传
String precreate = precreate(cloudPath, file.length(), 0, md5s.toString());
log.info("预上传{}", precreate);
//分片上传
String upload = upload(cloudPath, (String) new JSONObject(precreate).get("uploadid"), separate);
log.info("分片上传{}", upload);
//创建文件
String create = create(fileName, file.length(), 0, md5s.toString());
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(FILE_SEARCH + "&access_token=" + ATOKEN + "&key=" + fileName);
JSONObject jsonObject = new JSONObject(fileSearch);
JSONArray list = jsonObject.getJSONArray("list");
JSONObject listJSONObject = list.getJSONObject(0);
Long fs_id = listJSONObject.getLong("fs_id");
String url = DOWN_LOUE_URL + "?method=filemetas&access_token=" + 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 strURL = FILE_MANAGER_URL + "?method=create&access_token=" + ATOKEN;
String params = "path=" + APP_PATH + fileName + "&size=" + size + "&autoinit=1&block_list=["" + blockList + ""]&isdir=" + isDir;
return open(strURL, params, "POST");
}
/**
* @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 = SLICING_UPLOAD_FILE_URL + "?method=upload" +
"&access_token=" + ATOKEN +
"&type=tmpfile&partseq=" + i +
"&path=" + path +
"&uploadid=" + uploadid;
String s = sendFile(url, files[i]);
log.info("正在上传分片文件{}{}", s, 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 = GET_READY_FILE_URL + "?method=precreate&access_token=" + ATOKEN;
String params = "path=" + 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;
}
}
/**
* @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
*/
private 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;
}
}
最后
以上就是雪白口红为你收集整理的JAVA实现百度网盘文件上传的全部内容,希望文章能够帮你解决JAVA实现百度网盘文件上传所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复